Squash and Merge(이하 Squash Merge) 이후 Branch간 충돌로 인해 Rebase가 불가능한 경우가 있습니다. 충돌이 일어나는 이유와 해결 방법을 알아보겠습니다.
문제 상황
우선 Branch1에서 B, C commit 이후 다른 작업을 위해 Branch2를 만든 후 Branch 별로 각기 다른 작업을 진행했다고 가정하겠습니다.
Branch1의 작업이 끝나 Squash Merge 후 Main 브랜치를 Fast-Forward했습니다.
Branch2도 작업이 끝났습니다. 깔끔한 Commit history를 위해 Rebase를 진행하려고 합니다.
git checkout branch2
git rebase main
이렇듯 의식의 흐름대로 Rebase를 진행하면 여러분은 빨간색 글씨로 적힌 충돌 메세지를 맞이하게 되실 겁니다. 😫
문제 원인
Rebase는
- 두 Branch 사이의 공통 조상을 찾고,
- 공통 조상으로부터 Rebase할 Branch 내의 Commit들 사이의 변경사항을 저장해둔 후,
- Base가 될 Commit부터 2번에서 저장해둔 변경사항을 차례대로 적용합니다.
저희가 사용한 방식은 두 Branch 사이의 공통 조상이 C이니 Base Commit(G)부터 D와 E, E와 F 사이의 변경사항이 차례대로 적용될 것이라는 생각을 기반으로 합니다. 하지만 다시 한 번 생각해보면 Squash Merge 이후에 Branch1과 관련된 정보는 모두 G라는 Commit 하나에 담기지만, 외부에서는 G라는 Commit이 B와 C라는 Commit을 포함하고 있다는 사실을 알 방법이 없습니다. 그렇기 때문에 Git은 Rebase를 할 때 C가 아닌 A를 두 Branch의 공통 조상으로 인식하게 됩니다. 따라서 아래 그림4와 같이 이미 B, C Commit이 담긴 G Commit 이후에 다시 B, C Commit을 적용하게 되어 충돌이 발생하게 되는 것입니다.
해결 방법
간단하게 생각해보면 저희는 이미 G Commit이 B, C Commit을 포함하고 있는 것을 알고있기 때문에 Branch2에서 Rebase를 할 Commit을 E, F로만 한정한다면 위 문제를 해결할 수 있을 것 같습니다. 다행히 Git에서는 —onto라는 옵션을 통해 현재 HEAD를 포함한 N개의 Commit만 Rebase를 수행할 수 있습니다. 위 경우 Branch2의 HEAD인 F를 포함해 2개의 Commit만 Rebase할 때 이용하면 되기 때문에 아래 명령어를 통해 Rebase를 진행할 수 있습니다.
git rebase --onto main HEAD~2
만약 Squash Merge 이후에도 Branch1을 삭제하지 않은 경우 Commit 범위를 직접 지정하는 대신 아래 명령어를 통해 Main branch를 기준으로 Branch1에 존재하지 않으면서 Branch2에는 존재하는 Commit들만을 rebase해줄 수 있습니다.
git rebase --onto main branch1 branch2
잘못된 내용, 오타, 부정확한 문장 등 어떤 피드백이든 환영합니다. 감사합니다.
References
'CS > Git & Github' 카테고리의 다른 글
[Github] workflow scope 오류 해결하기 (0) | 2022.04.20 |
---|