개발/Git

[Git] Rebase와 Merge의 차이 by Visualizing-git

growing-dev 2023. 2. 2. 22:06

Rebase와 Merge의 차이 by Visualizing-git

Git에서 헷갈리는 개념 중 하나가 바로 Rebase와 Merge이다. 처음 Git을 접할 때 commit, push 정도는 쉽지만 branch들이 합쳐지는 과정에서 그래프도 복잡해지고 내 머리도 복잡해진다. branch를 어떻게 합치느냐에 따라 2가지 방식인 Rebase와 Merge가 존재하는데, 이 개념을 확실히 한다면 더 이상 Git이 복잡하게 느껴지지 않을 것이다. 

나는 Visualizing git이라는 사이트를 활용해서 이 개념을 빠르게 이해할 수 있어서 Rebase와 Merge에 대해서 소개하면서 실습을 이 사이트로 진행해 볼 예정이다.

 

https://git-school.github.io/visualizing-git/

 

Visualizing Git

 

git-school.github.io

 

 

Rebase에 대해서

git rebase [-i | --interactive] [<options>] [--exec <cmd>]
               [--onto <newbase> | --keep-base] [<upstream> [<branch>]]
git rebase [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]
               --root [<branch>]
git rebase (--continue | --skip | --abort | --quit | --edit-todo | --show-current-patch)

git rebase는 두 개의  branch를 합치는 작업의 방법의 하나로, 하나의 branch를 다른 branch의 base로 맞춰주는 명령어이다. 말 그대로 현재의 branch의 base를 해당 branch의 base로 맞춰준다.

rebase를 사용하는 가장 큰 목적은 commit history를 하나로 깔끔하게 관리하기 위해서이다. 내가 branch를 만들고 작업하는 동안에 origin branch가 수정이 되었을 때 내 작업 branch를 origin branch로 rebase를 하여 마치 최신 origin에서 처음부터 작업한 것 처럼 history를 맞출 수 있다. 이렇게 하면 이력관리가 잘되고 직관적이고 시간의 순서대로 하나의 흐름으로 이해할 수 있어서 관리하기 편리하다. 여러 사람이 작업할 때 rebase를 강제적으로 수행하는 곳이 굉장히 많은 것으로 알고 있다.

단점으로는 내 branch와 origin branch가 많이 다르거나 구조적인 내용이 수정되어 conflict가 발생한 경우에 내가 지금까지 쌓은 여러 commit들에 대해서 conflict를 하나씩 해결해 나가야 한다. history를 한줄로 쌓으려다 보니 발생할 수밖에 없는 일이다. 또 GitHub의 경우에는 PR(Pull Request)를 통해 반영될 때 Rebase를 하게 되면 항상 새로운 commit으로 생성되어 반영된다. 따라서 내 history와 GitHub remote origin이 무조건 달라지게 되어 불편하다.

그럼에도 불구하고 많은 조직에서 rebase를 많이 사용하는 것은 아무래도 관리적인 측면이 큰 것 같다. 개인이 조금 불편하더라도 history 및 이력관리 차원에서 하나의 줄기를 유지하는 것이 훨씬 직관적이고 관리하기 편하기 때문이다.

git rebase 예시

 

rebase 후 상황

위 예시에서 master 0c2d4fc 에서 분리되어 my_branch에 4개의 commit들이 쌓인 상태였다. 그리고 master는 3개의 commit들이 쌓인 상태였다. 나의 my_branch의 상태를 master의 최신 상태로 base를 조정하고 싶을 때 my_branch에서 git rebase master를 수행하였다. 이렇게 되면 my_branch와 master의 공통 base인 0c2d4 fc에서부터 현재 my_branch까지의 commit들이 master의 최신 상태를 base로 재배치되면서 새로운 commit id로 반영된다.

이렇게 되면 한 줄의 상태가 만들어지게 되는 것이다. 마치 내가 master의 최신 상태에서부터 4개의 작업을 한 것처럼 history가 작성이 되어 파악하기 편해진다.

 

master fast-forward

 

최종 상태

rebase를 하고 난 이후 master로 checkout 한 뒤 merge my_branch를 수행하면 두 개의 base가 이미 맞춰졌으므로 fast-forward 동작을 통해 최종적으로 하나의 동일한 상태로 맞춰지게 된다.

 

 

 

Merge에 대해서

Rebase 방식이 아니라면 Merge 방식으로 branch 간의 병합이 이루어 진다. Merge는 말 그대로 병합이므로 하나의 branch의 수정사항이 origin branch로 병합되면서 쌓여나가는 방식이다.

내 작업 branch에서 수정하는 동안 origin에서 수정이 발생해서 두 개가 달라진 경우에 origin에서 Merge를 수행하면 새로운 Merge commit이 생성되면서 작업 branch의 내용을 origin 위에 쌓게 된다. 이렇게 되면 두 branch가 합쳐진 것이라고 볼 수 있게 된다.

이 방식의 장점은 새로운 Merge commit을 통해 두 개의 branch가 쉽게 합쳐진다는 것이고 방식 자체가 Rebase에 비해 직관적이다. 또한 기존에 반영한 commit들이 그대로 유지된다는 점이다. 단점은 Merge commit으로 인해 전체적인 history가 복잡해지는 점이다.

git merge 예시
merge commit 생성

위 예제를 보면 my_branch와 master branch가 있고, 두개가 쭉 commit이 쌓인 상황이다.

my_branch의 32abcc8 이 내 branch의 최신 상태라고 가정하고, master 쪽으로 merge를 하고 싶은 상황이다.

이때 git checkout master를 통해 master로 이동하고 git merge my_branch를 통해 master에서 Merge commit을 발생시켜 my_branch를 통합한다.

이런 식으로 계속 반복이 된다고 보면 되는데, 개발자가 많고 그에 따라 branch가 많으면 history가 계속 복잡해질 것이다. 

 

 

결론

나는 개인적으로 왠만하면 Rebase를 강력 추천한다. 가장 중요한 것이 가독성, 간결성, 생산성이다. 그런 관점에서 origin, master의 상태가 깔끔하고 직관적인 것이 뭔가 찾거나 이해할 때도 좋고 관리하기도 좋다. 이를 위해 개발자들이 로컬에서 조금 더 작업을 해야겠지만 아무래도 대부분의 경우에는 Rebase가 좋을 것이라 확신한다.

 

반응형