developer tip

Git은 병합 문제를 어떻게 해결합니까?

copycodes 2020. 12. 30. 08:18
반응형

Git은 병합 문제를 어떻게 해결합니까?


SVN은 분기를 매우 저렴하게 만들어 분기를 훨씬 쉽게 만들었지 만 SVN에서는 병합이 여전히 실제 문제로 남아 있습니다.

Git은 이것을 어떻게 달성합니까?

(면책 조항 : Git에 대해 내가 아는 모든 것은 Linus 강의를 기반으로합니다-총 git noob 여기)


Git은 병합에서 충돌을 방지하지 않지만 부모 조상을 공유하지 않는 경우에도 기록을 조정할 수 있습니다.
( The grafts file ( .git/info/grafts)을 통해 한 줄에 하나씩 커밋과 그 부모가 따라 오는 목록으로 "조정"목적으로 수정할 수 있습니다.)
바로 거기에서 매우 강력합니다.

그러나 실제로 "병합이 어떻게 생각되었는지"를 엿 보려면 Linus 자신에게 문의 하여 시작 하면 이 문제가 "알고리즘"에 관한 것이 아니라는 것을 수 있습니다 .

Linus : 개인적 으로 저는 매우 반복적이고 영리하지 않은 무언가를 갖고 싶습니다. 내가 이해 하거나 할 수 없다고 말하는 것.
솔직히 말해서 다른 모든 파일의 히스토리를 고려 하지 않고 단일 파일 히스토리 병합 하면 "ugh"가됩니다.

병합의 중요한 부분은 충돌을 처리하는 방법이 아니라 (매우 흥미 롭다면 사람이 확인해야 함) 역사를 올바르게 결합하여 향후 병합을위한 새로운 견고한 기반을 확보해야한다는 것입니다. .

즉, 중요한 부분은 사소한 부분입니다. 부모의 이름을 지정하고 관계를 추적하는 것입니다. 충돌이 아닙니다.

그리고 SCM 직원의 99 %가 이에 대한 해결책이 콘텐츠 병합에 대해 더 현명하다고 생각하는 것 같습니다. 요점을 완전히 놓친 것입니다.


그래서 Wincent Colaiuta는 다음과 같이 덧붙입니다.

멋진 메타 데이터, 이름 변경 추적 등이 필요하지 않습니다.
저장해야하는 유일한 것은 각 변경 전후의 트리 상태입니다.

이름이 변경된 파일은 무엇입니까? 어떤 것이 복사 되었습니까? 어떤 것이 삭제 되었습니까? 어떤 줄이 추가 되었습니까? 어느 것이 제거 되었습니까? 내부에서 변경된 라인은 무엇입니까? 한 파일에서 다른 파일로 복사 된 텍스트 슬랩은 무엇입니까?
이러한 질문에 대해 신경 쓸 필요가 없으며 답을 돕기 위해 특별한 추적 데이터를 보관할 필요도 없습니다 . 트리의 모든 변경 (추가, 삭제, 이름 변경, 편집 등)은 암시 적으로 이루어집니다. 트리의 두 상태 사이의 델타로 인코딩됩니다 . 내용이 무엇인지 추적하기 만하면 됩니다 .

절대적으로 모든 것이 유추 될 수 있습니다 (그리고 그래야합니다) .

Git은 파일이 아닌 콘텐츠를 생각하기 때문에 틀을 깨뜨립니다.
이름 변경을 추적하지 않고 내용을 추적합니다. 그리고 그것은 전체 트리 수준에서 그렇게합니다.
이것은 대부분의 버전 제어 시스템에서 급격한 출발입니다.
파일 별 히스토리를 저장하는 데 신경 쓰지 않습니다. 대신 트리 레벨에서 히스토리를 저장합니다.
diff를 수행 할 때 두 개의 파일이 아닌 두 개의 트리를 비교합니다.

근본적으로 현명한 다른 디자인 결정은 Git이 병합하는 방법입니다.
병합 알고리즘은 영리하지만 너무 영리하려고하지 않습니다. 명확한 결정은 자동으로 이루어 지지만 의심스러운 경우 결정하는 것은 사용자의 몫입니다.
이것이야하는 방식입니다. 당신은 기계가 당신을 위해 결정을 내리는 것을 원하지 않습니다. 당신은 그것을 원하지 않을 것입니다.
이것이 합병에 대한 Git 접근 방식의 근본적인 통찰입니다. 다른 모든 버전 제어 시스템이 더 똑똑해 지려고 노력하는 동안 Git은 기꺼이 "멍청한 콘텐츠 관리자"라고 자칭하며 더 좋습니다.


이제는 현재 분기 ( '우리')의 버전, 병합 된 분기의 버전 ( '그들의')을 고려하는 3 방향 병합 알고리즘 (아마도 이름 바꾸기 감지 및 더 복잡한 기록 처리와 같은 개선 사항)에 일반적으로 동의합니다. ), 병합 된 분기의 공통 조상 ( '조상')의 버전은 (실제적인 관점에서) 병합을 해결하는 가장 좋은 방법입니다. 대부분의 경우, 대부분의 컨텐츠 트리 레벨 병합 (취할 파일 버전)이면 충분합니다. 콘텐츠 충돌을 처리 할 필요가 거의 없으며 diff3 알고리즘으로 충분합니다.

3 방향 병합을 사용하려면 병합 된 분기의 공통 조상을 알아야합니다 (통합베이스라고 함). 이를 위해서는 해당 지점 간의 전체 역사 를 알아야 합니다. (현재) 버전 1.5 이전의 Subversion에는 (SVK 또는 svnmerge와 같은 타사 도구가없는) 병합 추적 이있었습니다 . 즉, 병합에 사용 된 부모 (어떤 커밋)를 병합 커밋에 대해 기억하는 것입니다. 이 정보가 없으면 병합이 반복되는 경우 공통 조상을 올바르게 계산할 수 없습니다.

다음 다이어그램을 고려하십시오.

---.---a---.---b---d---.---1
        \        /
         \-.---c/------.---2

(아마 엉망이 될 것입니다 ... 여기에 ASCII 아트 다이어그램을 그릴 수있는 능력이 있으면 좋을 것입니다) .
커밋 'b'와 'c'(커밋 'd'생성)를 병합 할 때 공통 조상은 분기점 인 커밋 'a'였습니다. 그러나 커밋 '1'과 '2'를 병합하려는 경우 이제 공통 조상은 커밋 'c'입니다. 병합 정보를 저장하지 않으면 커밋 'a'라고 잘못 결론을 내려야합니다.

Subversion (버전 1.5 이전) 및 이전 CVS는 공통 조상을 직접 계산하고 병합 할 때 조상에 대한 정보를 수동으로 제공해야했기 때문에 병합을 어렵게했습니다.

Git은 커밋의 모든 부모 (병합 커밋의 경우 둘 이상의 부모)에 대한 정보를 커밋 개체에 저장합니다. 이렇게하면 Git이 수정본의 DAG (직접 비순환 그래프)를 저장하고 커밋 간의 관계를 저장하고 기억한다고 말할 수 있습니다.


(Subversion이 아래에 언급 된 문제를 어떻게 처리하는지 잘 모르겠습니다)

또한 Git에서 병합 하면 파일 이름 변경 (한 쪽에서 파일 이름을 바꾸고 다른 쪽에서 이름을 변경하지 않은 경우, 이름 바꾸기를 원하고 올바른 파일에 변경 사항을 적용하려는 경우) 및 교차 병합 이라는 두 가지 추가 문제를 해결할 수 있습니다 . (공통 조상이 둘 이상인 경우 더 복잡한 역사).

  • 병합 중 파일 이름 변경 은 발견 적 유사성 점수 기반 (파일 내용의 유사성과 경로 이름의 유사성을 모두 고려) 이름 변경 감지를 사용하여 관리됩니다 . Git은 병합 된 브랜치 (및 조상)에서 서로 대응하는 파일을 감지합니다. 실제로는 실제 상황에서 매우 잘 작동합니다.
  • 교차 병합 , revctrl.org wiki의 정의 참조 (및 다중 병합 기반의 존재 )는 단일 가상 공통 조상을 생성 하는 재귀 병합 전략 을 사용하여 관리됩니다 .

위의 답변은 모두 정확하지만 git의 쉬운 병합의 중심점을 놓친 것 같습니다. SVN 병합을 사용하려면 병합 된 항목을 추적하고 기억해야하며 이는 엄청난 PITA입니다. 문서에서 :

svn merge -r 23:30 file:///tmp/repos/trunk/vendors

이제 그것은 살인자가 아니지만 23-30 포함인지 23-30 독점인지 또는 이미 해당 커밋 중 일부를 병합했는지 여부를 잊어 버린 경우 피할 답을 찾아야합니다. 반복되거나 누락 된 커밋. 가지를 가지면 하나님이 도와 주 십니다.

git을 사용하면 git merge 일 뿐이며이 모든 것이 매끄럽게 이루어집니다. 두 개의 커밋을 선택했거나 환상적인 git-land 작업을 수행 한 경우에도 마찬가지입니다.


내가 아는 한 병합 알고리즘은 다른 버전 제어 시스템의 알고리즘보다 더 똑똑하지 않습니다. 그러나 git의 분산 된 특성으로 인해 중앙 집중식 병합 작업이 필요하지 않습니다. 모든 개발자는 언제든지 다른 개발자의 작은 변경 사항을 자신의 트리로 리베이스하거나 병합 할 수 있으므로 발생하는 충돌이 더 적은 경향이 있습니다.


Git은 잘못된 병합으로 다른 모든 사람의 저장소를 망치는 것을 더 어렵게 만듭니다.

유일한 진정한 이점은 모든 것이 로컬에서 수행되고 C로 작성되기 때문에 Git이 병합에서 훨씬 더 빠르다는 것입니다.

적절하게 사용되는 SVN은 완벽하게 사용할 수 있습니다.

참조 URL : https://stackoverflow.com/questions/612580/how-does-git-solve-the-merging-problem

반응형