Merge vs. Rebase

이번 하계 인턴을 하기 위한 총 4번의 면접에서 3번이나 물어봤지만 뚜렷하게 대답을 하지 못한 질문이 Merge와 Rebase의 차이였다. 브랜치를 합칠 때 항상 Merge를 써 왔는데 명확히 이 둘의 차이를 알아보고 싶었다. Merging vs. Rebasing를 참고하였다.

위와 같은 그림이 있을 때, master 브랜치에서 한 커밋이 지금 작업하고 있는 feature 브랜치와 관련이 있어 포함시켜야 할 상황을 가정해보자. 이 때 우리가 생각할 수 있는 방안은 merge와 rebase가 있다.

Merge

소스 트리 같은 도구를 이용해 쉽게 할 수 있지만 터미널에서 merge를 하는 방법은 이렇다.

1
2
3
4
5
git checkout feature
git merge master

// 또는
git merge master feature

이 작업은 두 브랜치의 최신본을 합치는 merge 커밋을 feature 브랜치에 생성한다. 다음과 같은 그림처럼 흐름이 합쳐진다.

merge가 좋은 이유는 비파괴적(non-destructive)이란 것이다. 각각의 브랜치에서 이루어진 커밋들이 흐름이 합쳐진 후에도 그대로 유지됨으로써 나중에 코드가 변경된 브랜치를 좀 더 쉽게 찾아갈 수 있다.

하지만 merge 커밋이라는 불필요한 커밋을 만든다는 점에서 단점이 있다. 명확한 코드의 변경에 대한 커밋 히스토리를 만들고 싶은데 불필요한 기록이 남게되는 것이다. 그래서 대안으로 rebase라는 옵션이 존재한다.

Rebase

마찬가지로 git 툴을 이용할 수 있고 터미널에서는 다음과 같이 rebase를 한다.

1
2
git checkout feature
git rebase master

이 작업은 master 브랜치의 변경점들을 모두 반영시키면서 feature 브랜치를 master 브랜치의 끝부분에서 시작하도록 이동시킨다. 즉, 한 번 정리를 해주고 가는 의미가 있다. 하지만 merge와는 달리 새로운 커밋을 생성하여 합치는 것이 아니라 원래 브랜치의 커밋마다 변경점이 반영된 새 커밋으로 변경함으로써 이루어진다.

rebase의 가장 큰 장점은 보다 깨끗한 커밋 히스토리를 만들 수 있다는 것이다. 불필요한 merge 커밋을 만들지 않으면서 위 그림과 같이 선형의 프로젝트 히스토리를 가질 수 있다.

하지만 rebase는 프로젝트 히스토리를 다시 쓰는 것이기 때문에 협업 시 주의를 해야 한다.

The Golden Rule of Rebasing

rebase를 하는 데 가장 중요한 규칙은 public 브랜치에서 하지 말아야 한다는 것이다. 예를 들어 위 상황과 반대로 master 브랜치를 feature 브랜치 위에 rebase 하는 상황을 가정해 보자.

이렇게 rebase를 할 경우 master의 모든 커밋이 feature 브랜치의 끝점으로 올라가게 된다. 여기서의 문제점은 다른 팀원들은 아직 master 브랜치를 사용하고 있다는 것이다. rebase는 새로운 커밋들로 바꾸기 때문에 master 브랜치가 팀원마다 다른 상황이 생기는 것이다.

다른 두 브랜치를 동기화시켜주는 방법은 merge를 하는 방법인데 역시 불필요한 merge 커밋이 생기고 같은 변경 사항을 담은 두 세트의 커밋이 남아있게 된다. 프로젝트의 히스토리가 더려워진다.

이러한 상황을 방지하기 위해 협업 시에 public 브랜치를 rebase하는 것은 신중하게 선택해야 한다.

Reference