Git 병합 커밋 재조정


183

다음과 같은 경우를 보자.

토픽 브랜치에 대한 작업이 있으며 이제 마스터로 다시 병합 할 준비가되었습니다.

* eb3b733 3     [master] [origin/master]
| * b62cae6 2   [topic]
|/  
* 38abeae 1

마스터에서 병합을 수행하고 충돌을 해결하면 다음과 같은 결과가 나타납니다.

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | eb3b733 3                     [origin/master]
|/  
* 38abeae 1

이제 병합에 어느 정도 시간이 걸렸으므로 다른 가져 오기를 수행하고 원격 마스터 분기에 새로운 변경 사항이 있음을 알 수 있습니다.

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
| | * e7affba 4                   [origin/master]
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

마스터에서 'git rebase origin / master'를 시도하면 모든 충돌을 다시 해결해야하며 병합 커밋도 손실됩니다.

* d4de423 2       [master]
* e7affba 4       [origin/master]
* eb3b733 3
| * b62cae6 2     [topic]
|/  
* 38abeae 1

병합 커밋을 리베이스하는 깔끔한 방법이 있습니까? 그래서 아래에 표시된 것과 같은 히스토리로 끝납니다.

*   51984c7 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | e7affba 4                     [origin/master]
* | eb3b733 3
|/  
* 38abeae 1

74
TL; DR :git rebase --preserve-merges origin/master
Ilia K.

6
충돌을 다시 해결 해야하는 경우 git rerere를 살펴 보십시오 .
Parker Coates

git config --global pull.rebase preserve rebase 동안 병합 커밋을 항상 보존하기 위해
galath

4
경고 : Git 2.18 (2018 년 2 분기, 5 년 후) git --rebase-merges부터는 이전을 대체 할 것 git --preserve-merges입니다. 참조 정확하게 망할 놈의는 "무엇을 rebase --preserve-merges"할 (왜?)
VonC

1
--preserve-merges더 이상 사용되지 않습니다. 사용git rebase --rebase-merges origin/master
Arjun Sreedharan

답변:


127

여기에는 두 가지 옵션이 있습니다.

하나는 대화식 리베이스를 수행하고 병합 커밋을 편집하고 병합을 수동으로 다시 실행 한 후 리베이스를 계속하는 것입니다.

또 다른 방법은 --rebase-mergeson 옵션 을 사용하는 것입니다 git rebase. "기본적으로 리베이스는 단순히 todo 목록에서 병합 커밋을 삭제하고 리베이스 된 커밋을 단일 선형 브랜치에 넣습니다. --rebase- 리베이스는 병합 커밋을 재생성함으로써 리베이스 될 커밋 내에서 분기 구조를 보존하려고 시도한다. 이러한 병합 커밋에서 해결 된 병합 충돌 또는 수동 수정은 수동으로 해결 / 재 적용되어야한다. "


16
-p 옵션을 시도했는데 실제로 커밋 기록을 그대로 두었지만 원산지 / 마스터에서 편집되지 않은 파일에서도 충돌을 다시 해결해야합니다. 첫 번째 제안에서 정확한 명령 순서는 무엇입니까?
jipumarino

2
@jipumarino : git rebase -i (병합 커밋을 편집하도록 알려주십시오), 병합 커밋에 도달하면 git reset --hard HEAD ^, git merge, 충돌 수정, git commit, git rebase --continue. 이런 종류의 일에 도움이되는 git rerere를보고 싶을 수도 있습니다 (그러나 결코 사용하지 않았으므로 조언이나 도움을 줄 수는 없습니다).
siride

2
감사. rerere를 활성화하고 rebase -p로 시도해 보았습니다.
jipumarino

3
다음은이 정확한 상황을 설명하는 훌륭한 블로그 게시물입니다 : 리베이스 병합 커밋 힘내에서
kynan

1
처음에는 병합을 수동으로 해결해야하므로 rere는 해결책이 아닙니다.
Flimm

29

좋아, 그것은 오래된 질문이며 이미의 답변을 수락 @siride했지만 내 경우에는 그 대답으로 충분하지 않았습니다 --preserve-merges. 모든 충돌을 두 번째로 해결해야합니다. 아이디어를 기반으로 @Tobi B하지만 정확한 단계별 명령으로 내 솔루션

따라서 우리는 질문의 예를 기반으로 그러한 상태에서 시작할 것입니다.

*   8101fe3 Merge branch 'topic'  [HEAD -> master]
|\  
| * b62cae6 2                     [topic]
| |
| | * f5a7ca8 5                   [origin/master]
| | * e7affba 4
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

우리는 2 개의 커밋을 먼저 마스터하므로 cherry-pick은 작동하지 않습니다.

  1. 우선, 우리가 원하는 정확한 역사를 만들어 봅시다 :

    git checkout -b correct-history # create new branch to save master for future
    git rebase --strategy=ours --preserve-merges origin/master
    

    --preserve-merges병합 커밋을 기록에 저장 하는 데 사용 합니다. --strategy=ours해당 병합 커밋에 어떤 내용이 포함 될지 신경 쓰지 않으므로 모든 병합 충돌을 무시 하는 데 사용 합니다. 지금은 멋진 기록 만 필요합니다.

    역사는 다음과 같습니다 (마스터 무시).

    *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    
  2. 이제 정확한 색인을 얻으십시오.

    git checkout master # return to our master branch
    git merge origin/master # merge origin/master on top of our master
    

    여기에 몇 가지 추가 병합 충돌이 발생할 수 있지만 , 8101fe3와 사이에 변경된 파일의 충돌 일 뿐이며 f5a7ca8이미 해결 된 충돌은 포함하지 않습니다.topic

    역사는 다음과 같습니다 (올바른 역사는 무시).

    *   94f1484 Merge branch 'origin/master'  [HEAD -> master]
    |\  
    * | f5a7ca8 5                   [origin/master]
    * | e7affba 4
    | *   8101fe3 Merge branch 'topic'
    | |\  
    | | * b62cae6 2                     [topic]
    |/ /
    * / eb3b733 3
    |/  
    * 38abeae 1
    
  3. 마지막 단계는 지점을 올바른 기록으로 결합하고 지점을 정확한 색인으로 결합하는 것입니다

    git reset --soft correct-history
    git commit --amend
    

    우리는 reset --soft분기 (및 기록)를 올바른 기록으로 재설정하지만 색인과 작업 트리는 그대로 둡니다. 그런 다음 commit --amend마스터의 올바른 인덱스로 잘못된 인덱스를 가진 병합 커밋을 다시 작성하는 데 사용합니다.

    결국 우리는 그러한 상태를 가질 것입니다 (또 다른 최고 커밋 ID를 주목하십시오) :

    *   13e6d03 Merge branch 'topic'  [HEAD -> master]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    

이것은 굉장하고 많은 도움이되었습니다! 그러나 나는 commit --amend으로 트릭을 얻지 못했습니다 : 그것에 대해 더 많은 정보를 추가 할 수 있습니까? 당신이 그것을 실행 한 후에 정확히 어떻게됩니까-커밋의 SHA가 변경되었음을 알았습니다. 그러나 왜? 아니면 이것을 실행하지 않으면 어떻게됩니까?
ZenJ

1
@ZenJ git commit --amend는 마지막 커밋 (이 경우 HEAD, 병합 커밋)에 변경 사항을 추가합니다. 커밋 내용이 변경되므로 해시가 업데이트됩니다.
Dries Staelens

1
충돌을 수정하기 전에 'rerere'를 사용하지 않는 사람들의 경우이 솔루션은 충돌을 다시 수정하지 않아도되기 때문에 좋습니다. 감사!
Shackleford

6

나는 이것을 알아 내려고 하루를 잃고 실제로 동료의 도움으로 해결책을 찾았다는 것을 감안할 때, 나는 차임해야한다고 생각했다.

우리는 큰 코드 기반을 가지고 있으며 동시에 2 개의 크게 수정되는 것을 처리해야합니다. 메인 브랜치와 보조 브랜치가 있습니다.

보조 브랜치를 메인 브랜치로 병합하는 동안 메인 브랜치에서 작업이 계속되고 완료 될 때까지 변경 사항이 호환되지 않기 때문에 변경 사항을 적용 할 수 없습니다.

따라서 "병합"을 "리베이스"해야합니다.

이것이 우리가 마침내 한 방법입니다.

1) SHA를 기록하십시오. 예 : c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

2) 적절한 기록을 작성하지만 병합이 중단됩니다.

git rebase -s ours --preserve-merges origin/master

3) SHA를 기록하십시오. 예 : 29dd8101d78

git log -1

4) 이제 이전 위치로 재설정

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) 이제 현재 마스터를 작업 지점에 병합하십시오.

git merge origin/master
git mergetool
git commit -m"correct files

6) 이제 올바른 파일을 가지고 있지만 잘못된 기록은 다음과 같이 변경 사항 위에 올바른 기록을 가져옵니다.

git reset 29dd8101d78 --soft

7) 그런 다음 원래 병합 커밋의 결과를 수정하십시오.

git commit --amend

짜잔!


1

첫 번째 병합을 제거하는 것 같습니다. 다음 절차를 따를 수 있습니다.

git checkout master      # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull                 # or git merge remote/master
git merge topic

그것은 당신이 원하는 것을 줄 것입니다.


4
rerere가 활성화되면, 이것은 siride가 제공 한 rebase -p 솔루션과 동일한 결과를 제공하는 것으로 보입니다.
jipumarino

0
  • 병합 커밋에서
  • 쉬워야 할 새로운 변화를 체리 픽
  • 당신의 물건을 복사
  • 병합을 다시 실행하고 로컬 사본에서 파일을 복사하여 충돌을 해결하십시오.)

1
이 답변은 좋아 보이지만 사용자가 git을 처음 사용하는 경우 실제 git 명령을 제공하면 더 유용합니다
Louise Davies
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.