개발/Developing

Git Rebase된 브랜치에 또 Rebase 하기

lazykuna 2022. 8. 24. 15:45

제목을 뭘로 지어야 하나 싶어서 고민하다가 ... 이렇게 지어버렸다 😅

상황은 이렇다.

  1. main 에서 A 브랜치를 새로 만들고 작업함
  2. A 브랜치에서 A2 브랜치를 새로 만들고 작업함
  3. 와중에 A 브랜치가 main으로 rebase 후 merge 됨
  4. 이제 A2 브랜치를 main으로 merge 하려고 함

이러면 이제 엄청난 conflict의 향연을 보게 된다.

강호동도 경악할만한 컨플릭 목록

아니, A 커밋이 merge된 곳을 기점으로 당연히 알아서 conflict resolve 해줄 것 같았는데 이게 무슨 일이람!!

사건의 전말은 아래와 같다.

  • A2 브랜치는 A 브랜치의 커밋 ID를 보고 자동으로 머지를 수행함
  • A 브랜치가 main으로 rebase merge가 됨 => (1)에서의 커밋 ID가 없어짐
  • 동시에 자동으로 A2 브랜치의 target merge branch가 main으로 바뀌면서, A 브랜치의 커밋과 target commit ID를 가지고 오게 됨 => 중복 커밋을 시도하게 되어 merge conflict가 발생하게 됨

대충 그림으로 그리면 아래와 같은 상황이 되지 않을까?

M1---M2---M3 (main)
          \
           A1---A2---A3 (A)
                      \
                       A'1---A'2 (A2)

# after rebase A
M1---M2---M3---A (main)
                \
                 A1---A2---A3---A'1---A'2(A2)

이미 A1~A3은 반영되어 있어서 다시 머지될 필요가 없는데, git이 제대로 커밋을 잡아주지 못하고 있는 듯 하다.

이 때 쓸수 있는 옵션이 git rebase --onto 이다.

git rebase --onto <A> <A3>

이런 식으로 쓰면, A와 A3을 이미 병합된 커밋인 것으로 간주하여 묶고 그 위 commit(A'1)에 대해서 rebase를 하게 해준다. git rebase 자체가 `--onto <target> <base>`인 셈이니...

(A2) 브랜치에서 이렇게 명령을 수행하면, 아래와 같이 커밋이 정리된다.

M1---M2---M3---A (main)
                \
                 A'1---A'2 (A2)

 

종종 있을만한 일인데 git 명령어와 commit tree에 대한 개념이 없으면 다소 사용하기 어려운 고급(?) 명령어 축에 속하는 것 같다. 그래서 글로 남겨 둠!

참고: https://womanonrails.com/git-rebase-onto