2014-01-23 3 views
3

git 색인에 포함 된 내용이 git-addgit-commit 일 때 퍼지 아이디어가 있지만, git-merge을 수행 할 때 이러한 내용이 어떻게되는지 알 수는 없습니다. 특히 병합이 실패 할 때 인덱스가 보유하고있는 내용 (예 : 충돌로 인해)을 배우는 데 관심이 있습니다.병합 중에 git 인덱스의 내용이 어떻게 전개 되나요? (병합 실패 후 인덱스에있는 내용은 어떻게됩니까?)

+0

병합 및 리베이스는 몇 가지 점에서 유사합니다. 어쩌면'git rebase -i'를 실행하고'pick'을'edit'로 대체 한 다음 .git 수정을 관찰함으로써 어떤 일이 일어날 지 알 수 있습니다. – Asenar

+0

@Asenar :'rebase'는 일련의'cherry-pick' 내부적으로 연산을 수행하고, 체리 선택 컷 (commit-commited commit)마다 git은 병합 메커니즘을 사용하여 해당 커밋에 의해 암시 된 변경 사항을 적용합니다. – torek

+0

그 정밀도에 감사드립니다. – Asenar

답변

2

인덱스에는 "0"부터 "3"까지 최대 4 개의 "버전 번호"가 있습니다. 실제로 모든 항목에 대해 마치 "슬롯"이라고 부릅니다. 실제로 추가 버전은 필요할 때만 동적으로 도입 되기는하지만 쉽게 색인화됩니다 (이것으로 인해 더 쉽게 생각할 수 있습니다). 이 "가상 슬롯"은 "비어있을"수 있습니다. 즉, 파일이 존재하지 않습니다.

(사실, 색인에 항목이 만들어지면 필요에 따라 CE_REMOVED 플래그 비트가 표시됩니다. 파일이 가득 찬 전체 디렉토리를 "제거됨"으로 표시하고 파일을 표시 할 수 있으므로 털이 있습니다. 이전 디렉토리의 이름으로 생성되고 "추가됨"으로 표시되는 대신 고정 슬롯이있는 것처럼 가장 해보자 :-))

슬롯 # 0은 "정상적인"충돌없는 , 모든 - 잘 - 항목. 저장소에 저장된 파일의 캐시 데이터, 경로 이름 및 BLOB-ID (SHA-1)를 포함합니다.

병합이 성공하면 모두 "정상적으로 업무를 수행하고 있으므로"유일하게 특별한 경우는 충돌하는 병합입니다. 슬롯 1, 2 및/또는 3이 비어 있지 않으면 병합이 "충돌"됩니다. 대부분의 메 커닉을 건너 뛰면 어떻게됩니까? 병합은 모든 슬롯은 "최신"이름을 사용하고 :

  • 슬롯 제로 (당신이 충돌을 해결할 때까지 한 시간이 슬롯이 비어있을 수 없습니다 것 "커밋"할 수없는 비어 더 이상 파일을 정말로 삭제하지 않는 한).
  • 슬롯 1 ("base")은 공통 조상 버전으로 채워집니다. 파일이 새 버전 인 경우 (개정판 모두)이 슬롯은 비어 있습니다.
  • 슬롯 2 ("우리")는 타겟 (기본 병합 기계를 수동으로 호출하지 않는 한 HEAD) 버전으로 채워집니다. 파일이 HEAD/target-of-merge에서 제거 된 경우이 슬롯은 대신 비어 있습니다.
  • 슬롯 3 ("theirs")은 병합중인 버전으로 채워집니다. 병합중인 개정에서 파일이 제거 된 경우이 슬롯은 비어 있습니다.

"git add"와 충돌이 해결되면 # 1에서 # 3까지의 항목을 지우기 위해 # 0 슬롯에 "add"가 채워집니다. 또는 "git rm" 충돌 한 파일, 다른 스테이지 항목은 여전히 ​​제거되지만 이제는 # 0 슬롯이 비어 있으며 충돌을 해결합니다.

더 구체적으로, 다음, 당신이 (다른 사람들)가 공통 조상이 두 파일이 있다고 가정

gronk 
flibby 

당신은 지점 cleanup에있어 당신이 breemgronk 이름을 변경, 모두 편집 한 그 및 flibby. git merge work으로 변경하고 gronk을 수정했지만 이름을 바꾸지 않았으며 flibby을 삭제했습니다. 일부 다른 파일이 깔끔하게 병합되었습니다.당신은 git show :1:bleembleem의 원래 (기본) 버전을 볼 수 있습니다

$ git checkout cleanup 
Switched to branch 'cleanup' 
$ git merge work 
CONFLICT (modify/delete): flibby deleted in work and modified 
in HEAD. Version HEAD of flibby left in tree. 
Auto-merging bleem 
CONFLICT (content): Merge conflict in bleem 
Automatic merge failed; fix conflicts and then commit the result. 
$ git ls-files --stage 
100644 4362aba7f3b7abf2da0d0ed558cbf5bc0d12e4b0 1 bleem 
100644 49db92a61392e9fd691c4af6e1221f408452a128 2 bleem 
100644 04b399c8fe321902ce97a1538248878756678ca2 3 bleem 
100644 366b52546711401122b791457793a38c033838dd 1 flibby 
100644 6fecb1480f45faaabc31b18c91262d03d3767cde 2 flibby 
100644 7129c6edb96d08bb44ca1025eb5ae41d41be8903 0 x.txt 

:

지수는 bleem의 세 가지 버전 및 flibby의 두 가지 버전이 포함됩니다. 이 버전의 기본 버전은 gronk (이 경우는 work)이지만, bleem이라고하는 이유는 gronk에서 bleem으로 변경하고 cleanup으로 변경했기 때문입니다. (힘내 병합 계와 HEAD의 이름 변경을 발견하고 필요한 경우,이 경우에서와 같이, work 동일한 이름 변경을 적용한다.)

을 마찬가지로이 git show :3:bleem 또는 git show work:gronkwork 버전을 볼 수 있고, HEAD 버전 git show HEAD:bleem, git show cleanup:bleem 또는 git show :2:bleem (슬롯 2에는 HEAD (cleanup 버전)이라는 별칭이 포함되어 있으며 이름은 HEAD입니다.

flibby의 경우 work에서 제거되었으므로 "theirs"(슬롯 3) 버전이 없습니다.

충돌을 해결하려면 슬롯 0 항목을 업데이트하고 1- 통과 3 항목을 제거하려면 git add 또는 git rm이라고 말해야합니다. 물론 git add을 사용하면 슬롯 0으로 바꾼다. 이제는 작업 디렉토리에있는 것이므로 일반적으로 먼저 파일을 편집해야한다.

덧붙여서 위의 2와 3 슬롯에는 "ours"와 "theirs"가 표시되어 있습니다. 이것은 git checkout도 마찬가지로 처리합니다 (git checkout --oursgit checkout --theirs). 슬롯 2에 버전 2 또는 3을 쓰게하고 대부분 체크 아웃과 마찬가지로 다른 슬롯도 "지우"하여 충돌을 해결합니다. 그러나 리베이스의 경우 HEAD 브랜치는 실제로 리베이스 된 브랜치이고 "theirs"버전은 브랜치가 리베이스됩니다. 그래서 우리/그들의 용어는 정말로 훌륭하지 않습니다. 제 의견으로는, 리베이스하는 동안 뒤로 가져가는 것이 너무 쉽습니다.

또한 병합 된 충돌이 발생한 경우이 슬롯 0을 지우고 필요에 따라 슬롯 1 ~ 3의 버전을 "다시 활성화"하여 병합 충돌을 "다시 만듭니다" 작업 디렉토리에 충돌 한 병합 파일을 쓰거나, merge.conflictstyle 설정의 변경 사항을 따르십시오).

+0

이것은 아주 좋은 대답입니다. –