복구: 집합 파일 합병의 왕복 신뢰도 손상

4682 단어 hg-git
4

묘사

이러한 상황에서 변경 집합을 Mercurial에서 Git로 밀어 넣은 다음에 다시 끌어오면 서로 다른 변경 집합 ID(그리고 경미한 저장소 손상을 초래할 수 있다. 이것은 복제 검사와 같은 일부 조작을 파괴할 수 있다)를 발견했다.
토론한 변경 집합이 하나의 합병일 때 이런 상황이 발생한다. 이 합병에 포함된 파일은 두 개의 부모 등급에서 같은 내용을 가지지만 서로 다른 역사 기록을 통해 이러한 내용을 얻는다. (따라서 Mercurial에서 서로 다른 파일 수정을 가진다.)Mercurial은 이러한 결합을 수행할 때 두 상위 개정을 결합한 새 파일 개정을 작성하여 상위 개정 두 개를 결합합니다. 따라서 변경 내용이 상위 개정에 비해 변경되지 않았더라도 결합에서 보고합니다.한편, Git는 과거 기록이 아닌 파일 내용만 추적하기 때문에 Git를 가져온 후에 파일의 변경 사항을 보고하지 않는다.병합을 Mercurial로 되돌릴 때, Hg Git는 병합된 파일 버전을 다시 만들어야 합니다. Git가 알려주지 않아도.현재는 그렇지 않지만, 첫 번째 부모 단계의 파일 수정을 보류하고, 결과는 1이다.변경 세트 ID는 원래 ID와 다르며 2입니다.파일 로그 히스토리는 교차하지 않으며 변경 세트 히스토리와 일치하지 않으므로 두 번째 상위 히스토리의 조상으로 돌아가려고 하면 파일 히스토리를 따라 반환된 활동(예: 병합 시 복사 체크)이 실패합니다.
첫 번째 부모에서 전체 파일 내용을 가져오고 두 번째 부모의 변경 사항을 포기함으로써 합병 충돌을 해결할 때도 마찬가지다.
다음 셸 스크립트에서는 원래 버전 ID와 역으로 가져온 버전 ID가 다른 이유와 함께 이 문제를 재현합니다.
hg init hgrepo1
cd hgrepo1
echo A > afile
hg add afile 
hg ci -m "origin"
echo B > afile
hg ci -m "A->B"
echo C > afile
hg ci -m "B->C"
hg up -r0
echo C > afile
hg ci -m "A->C"
hg merge -r2
hg ci -m "merge"
hg log --template "{node}\n" -r tip > ../mergeid-orig
cd ..
git init --bare gitrepo
cd hgrepo1
hg bookmark -r4 master
hg push -r master ../gitrepo
cd ..
hg init hgrepo2
cd hgrepo2              
hg pull -r master ../gitrepo
hg log --template "{node}\n" -r tip > ../mergeid-from-git
cd ..
cmp mergeid-orig mergeid-from-git && echo equal || echo different

hg debugindex hgrepo1/.hg/store/data/afile.i
hg debugindex hgrepo2/.hg/store/data/afile.i
추가 제출은 문제에 테스트 (현재 실패) 와 복구 (테스트를 성공시키고, 실패하지 않은 다른 테스트를 파괴하지 않습니다) 를 추가합니다.감사합니다.훌륭한 탐정 작업!
2011년 5월 24일 화요일 오후 1:49, 크왈트
[email protected]
쓰기:

I have found a circumstance in which pushing a changeset from Mercurial to Git, then pulling it back again will result in a different changeset ID (as well as slight repository corruption that will break some operations such as copy detection).

This happens when the changeset in question is a merge that contains files that had the same contents in both parents, but arrived at those contents by different histories (and therefore have different file revisions in Mercurial). When making such a merge, Mercurial will create a new file revision that ties together the two parent revisions, and therefore reports the file as changed in the merge, even though its content did not change with respect to either parent. Git on the other hand only tracks file contents, not their histories, and will therefore not report the file as changed after importing that merge into Git. On pulling back the merge into Mercurial, Hg-Git must recreate the merged file revision, even though it is not told so by Git. It currently does not do that, but keeps the file revision from the first parent, with the result that 1. the changeset ID is different from the original, and 2. the filelog history is disjoint and doesn’t match the changeset history  , so that activities that travel back along the file history, e.g. copy detection while merging, will fail when trying to go back to an ancestor that lies in the history of the second parent.

The same thing also happens when a merge conflict is resolved by taking the entire file contents from the first parent and discarding any changes from the second parent.

The following shell script will reproduce the issue, showing that the original and back-imported revision IDs are different, and why:

``` hg init hgrepo1 cd hgrepo1 echo A > afile hg add afile hg ci -m "origin" echo B > afile hg ci -m "A->B" echo C > afile hg ci -m "B->C" hg up -r0 echo C > afile hg ci -m "A->C" hg merge -r2 hg ci -m "merge" hg log --template "{node}\n" -r tip > ../mergeid-orig cd .. git init --bare gitrepo cd hgrepo1 hg bookmark -r4 master hg push -r master ../gitrepo cd .. hg init hgrepo2 cd hgrepo2 hg pull -r master ../gitrepo hg log --template "{node}\n" -r tip > ../mergeid-from-git cd .. cmp mergeid-orig mergeid-from-git && echo equal || echo different

hg debugindex hgrepo1/.hg/store/data/afile.i hg debugindex hgrepo2/.hg/store/data/afile.i ```

The attached commits add a test for the problem (that currently fails) and a fix (that makes the test succeed and doesn’t break any other tests that weren’t failing already).

Reply to this email directly or view it on GitHub: https://github.com/schacon/hg-git/pull/207

토론 #1

고마워요, 너무 빨라요!

좋은 웹페이지 즐겨찾기