git
색인에 포함 된 내용이 git-add
및 git-commit
일 때 퍼지 아이디어가 있지만, git-merge
을 수행 할 때 이러한 내용이 어떻게되는지 알 수는 없습니다. 특히 병합이 실패 할 때 인덱스가 보유하고있는 내용 (예 : 충돌로 인해)을 배우는 데 관심이 있습니다.병합 중에 git 인덱스의 내용이 어떻게 전개 되나요? (병합 실패 후 인덱스에있는 내용은 어떻게됩니까?)
답변
인덱스에는 "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
에있어 당신이 breem
에 gronk
이름을 변경, 모두 편집 한 그 및 flibby
. git merge work
으로 변경하고 gronk
을 수정했지만 이름을 바꾸지 않았으며 flibby
을 삭제했습니다. 일부 다른 파일이 깔끔하게 병합되었습니다.당신은 git show :1:bleem
와 bleem
의 원래 (기본) 버전을 볼 수 있습니다
$ 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:gronk
와 work
버전을 볼 수 있고, 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 --ours
및 git checkout --theirs
). 슬롯 2에 버전 2 또는 3을 쓰게하고 대부분 체크 아웃과 마찬가지로 다른 슬롯도 "지우"하여 충돌을 해결합니다. 그러나 리베이스의 경우 HEAD
브랜치는 실제로 리베이스 된 브랜치이고 "theirs"버전은 브랜치가 리베이스됩니다. 그래서 우리/그들의 용어는 정말로 훌륭하지 않습니다. 제 의견으로는, 리베이스하는 동안 뒤로 가져가는 것이 너무 쉽습니다.
또한 병합 된 충돌이 발생한 경우이 슬롯 0을 지우고 필요에 따라 슬롯 1 ~ 3의 버전을 "다시 활성화"하여 병합 충돌을 "다시 만듭니다" 작업 디렉토리에 충돌 한 병합 파일을 쓰거나, merge.conflictstyle
설정의 변경 사항을 따르십시오).
이것은 아주 좋은 대답입니다. –
병합 및 리베이스는 몇 가지 점에서 유사합니다. 어쩌면'git rebase -i'를 실행하고'pick'을'edit'로 대체 한 다음 .git 수정을 관찰함으로써 어떤 일이 일어날 지 알 수 있습니다. – Asenar
@Asenar :'rebase'는 일련의'cherry-pick' 내부적으로 연산을 수행하고, 체리 선택 컷 (commit-commited commit)마다 git은 병합 메커니즘을 사용하여 해당 커밋에 의해 암시 된 변경 사항을 적용합니다. – torek
그 정밀도에 감사드립니다. – Asenar