마스터에 병합 할 때 첫 번째 분기가 스쿼시 된 후 분기의 분기 병합


81

다음은 직장에서 일반적으로 다루는 워크 플로입니다.

git checkout -b feature_branch
# Do some development
git add .
git commit
git push origin feature_branch

이 시점에서 기능 브랜치는 동료들의 검토를 받고 있지만 .NET에 종속 된 다른 기능을 계속 개발하고 싶습니다 feature_branch. 그래서 feature_branch검토 하는 동안 ...

git checkout feature_branch
git checkout -b dependent_branch
# Do some more development
git add .
git commit

이제 feature_branch의 코드 검토에 대한 응답으로 몇 가지를 변경합니다.

git checkout feature_branch
# Do review fixes
git add .
git commit
git checkout dependent_branch
git merge feature_branch

이제 여기에서 문제가 생깁니다. master에 대한 스쿼시 정책이 있습니다. 즉, master에 병합 된 기능 분기를 단일 커밋으로 스쿼시해야합니다.

git checkout feature_branch
git log # Look for hash at beginning of branch
git rebase -i  first_hash_of_branch # Squash feature_branch into a single commit
git merge master

를 제외하고 모든 것이 멋집니다 dependent_branch. 종속 브랜치를 마스터로 리베이스하거나 마스터를 마스터로 병합하려고 할 때 git은 다시 작성 / 스쿼시 된 기록에 혼란스럽고 기본적으로 모든 변경 사항을 depedendent_branch충돌로 표시합니다. .NET의 모든 변경 사항을 거치고 기본적으로 다시 수행하거나 충돌을 해제하는 것은 PITA입니다 dependent_branch. 이것에 대한 해결책이 있습니까? 때로는 수동으로 패치를 만들어 마스터의 새로운 브랜치에 적용 하겠지만 실제 충돌이있는 경우 수정하는 것이 더 나쁩니다.

git checkout dependent_branch
git diff > ~/Desktop/dependent_branch.diff
git checkout master
git checkout -b new_dependent_branch
patch -p1 < ~/Desktop/dependent_branch.diff
# Pray for a clean apply.

어떤 아이디어? 스쿼시 동안 재 작성된 기록 때문에 이런 일이 발생한다는 것을 알고 있지만 변경할 수없는 요구 사항입니다. 최상의 솔루션 / 해결 방법은 무엇입니까? 내가 할 수있는 마법이 있나요? 아니면 수동으로 diff를 만드는 것과 관련된 모든 단계를 수행하는 더 빠른 방법이 있습니까?


제쳐두고, git add .완전히 사악하며 의도하지 않은 일을 저지르면 결국 당신을 물게 될 것입니다. 당신은 사용해야 git add -p하거나 적어도git add -u .
meagar

1
코드 검토를 변경 한 후에는 dependent_branch를 기능 브랜치로 리베이스해야합니다. 그런 다음 마스터로 이동할 준비가되면 기능 브랜치를 마스터로 리베이스하고 커밋을 스쿼시 한 ​​다음 기능 브랜치를 마스터로 병합합니다.

답변:


108

왜 이런 일이 발생하는지에 대해 조금 :

나는 드리겠습니다 O될 "원본 마스터"와 FB기능 지점이되어에서 합병 후, "새 마스터"수 :

feature_branch다음과 같이 말합니다 .

O - A - B - C 

dependent_feature 그 위에 몇 가지 추가 커밋이 있습니다.

O - A - B - C - D - E - F

원래 기능 브랜치를 마스터로 병합하고 아래로 스쿼시하여 다음을 제공합니다.

O - FB

이제 종속 브랜치를 리베이스하려고 할 때 git은 해당 브랜치 간의 공통 조상을 파악하려고합니다. 원래 였을 것이지만 C커밋을 스쿼시하지 않았다면 대신 git O이 공통 조상으로 찾습니다 . 그 결과, 자식은 재생하려고하는 A, B그리고 C어떤이되어 이미 포함FB, 당신은 충돌의 무리를 얻을 것입니다.

이러한 이유로 일반적인 rebase 명령에 실제로 의존 할 수 없으며 --onto매개 변수 를 제공하여 더 명확하게 설명해야합니다 .

git rebase --onto master HEAD~3  # instruct git to replay only the last
                                 # 3 commits, D E and F, onto master.

HEAD~3분기에 필요한대로 매개 변수를 수정하면 중복 충돌 해결을 처리 할 필요가 없습니다.

범위 지정이 마음에 들지 않고 원래 기능 브랜치를 아직 삭제하지 않은 경우 일부 대체 구문 :

git rebase --onto master feature_branch dependent_feature

                                 # replay all commits, starting at feature_branch
                                 # exclusive, through dependent_feature inclusive 
                                 # onto master

--onto를 사용할 때 master의 git 트리가 어떻게 다른지보고 싶었습니다. 또는 --onto가 어떻게 다른지에 대해 조금 더 이해하는 다른 방법 일 수도 있습니다.
Abhishek Anand

3
--onto를 사용하면 브랜치에서 재생하려는 커밋에 대해 더 선택적으로 지정할 수 있습니다 . 기본적으로 git은 어떤 커밋이 재생되어야하는지 "확인"하려고합니다. --onto를 사용하면 특정 범위의 커밋 을 재생하도록 git에 명시 적으로 지시 합니다. 내 예에서 --onto를 사용하지 않으면 O-FB-A-B-C-D-E-F 및 FB와 A-B-C가 동일한 변경 사항을 포함하기 때문에 수많은 병합 충돌이 발생합니다. --onto를 사용하고 마지막 3 개의 커밋을 지정하면 원래 asker가 찾고 있던 O-FB-D-E-F로 끝납니다.
joshtkling

2

이 특별한 경우에는 당신이 원래 작업했던 브랜치의 스쿼시 된 작업 만이 마스터에 들어갔다는 것을 "알고있는"것 같습니다 .

따라서 갈등이있을 때마다 변경 사항을 유지하여 행복하게 병합 할 수 있습니다. 이에 대한 옵션이 있습니다.

git merge -Xours master

자세한 내용은 https://git-scm.com/docs/git-rebase 를 참조하십시오.


1
불행히도 그렇지 않을 수도 있습니다. feature_branch와 dependent_branch에 대한 코드 검토 사이에 시간이있는 경우 feature_branch가 병합되고 푸시 될 수 있으며 다른 사람이 dependent_branch가 도착하기 전에 충돌하는 것을 추가 할 수 있습니다.
마이크

0

나는 "모든 기능 개발을 단일 커밋으로 매시"정책에 진심으로 동의하지 않지만, 그것이 그들의 요구입니다.

나는 브랜치를있는 그대로 유지하고 특별한 브랜치에서 출판만을위한 매쉬업 커밋을 생성 할 것입니다. 경영진이 그것을 믿지 않더라도 단계적으로 개발을 따를 수 있다는 것은 가치가 있습니다. "실제"브랜치의 태그로 스쿼시 위치를 표시합니다. 실제 커밋을 다시 가리키는 메시지와 함께 스쿼시 태그 사이에 추가 할 수도 있습니다.


나는 실제로 그 스 쿼싱을 좋아하지만 그것은 실제로 arccanist가 수행하고 기능 브랜치에 대한 모든 개발 / 커밋 / 코드 검토가 phabricator에 저장되어 있기 때문입니다 ...하지만 귀하의 요점은 확실합니다.
마이크
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.