제목을 뭘로 지어야 하나 싶어서 고민하다가 ... 이렇게 지어버렸다 😅
상황은 이렇다.
- main 에서 A 브랜치를 새로 만들고 작업함
- A 브랜치에서 A2 브랜치를 새로 만들고 작업함
- 와중에 A 브랜치가 main으로 rebase 후 merge 됨
- 이제 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에 대한 개념이 없으면 다소 사용하기 어려운 고급(?) 명령어 축에 속하는 것 같다. 그래서 글로 남겨 둠!
'개발 > Developing' 카테고리의 다른 글
Golang의 defer의 변수 캡쳐, 그리고 동작 원리 (0) | 2023.04.02 |
---|---|
Python에서의 yield와 실행 순서 (0) | 2023.03.28 |
Thread-safe queue design (0) | 2022.08.06 |
CORS 요청이 이루어지기까지 (0) | 2022.08.06 |
Node.js + typescript 에서 gRPC 사용하기 (0) | 2022.06.18 |