두 브랜치를 하나로
git 을 쓰면서 두 개의 브랜치를 하나의 브랜치로 합치는 방법은 merge 와rebase 가 있습니다.
merge 와 rebase 가 어떻게 두 브랜치를 하나의 브랜치로 합쳐 주는지, 어떤 차이점이 있는지에 대해 포스팅 하려 합니다.
Merge
Fast-Forward Merge
merge 명령어를 사용해서 두 브랜치는 합치는 경우를 예제를 통해 살펴보겠습니다.
현재 마스터 브랜치에는 C1, C2 커밋이 있다고 가정하겠습니다.
현재 master 브랜치에서 A 브랜치를 생성 후 C3, C4 작업을 수행합니다.
작업이 끝난 후 A 브랜치를 master 브랜치에 merge 해보겠습니다.
C4 커밋은 C2 커밋에 기반했기 때문에 별도 합치는 과정 없이 Master 브랜치가 C4 커밋을 바라보게만 했습니다. 이를 Fast-forward 라고 합니다.
3-way merge
현재 상황에서 master 는 C5 작업을 A 브랜치는 C6 작업을 했다고 하겠습니다.
이제 A 브랜치를 master 브랜치에 merge 해보겠습니다.
방금 전과는 다른 메시지가 나옵니다.
머지를 하는 시점에서 Master 브랜치의 C5 가 A 의 C6 이 Base 가 아닐때는 C5 와 C6 의 공통조상(C4) 을 찾고 C4, C5, C6 3개의 커밋을 merge 합니다.
C4, C5, C6 를 merge 한 커밋을 하나 만들고 (m), master 브랜치가 m 커밋을 보도록 하는 방식을 3-way merge 라고 합니다.
merge 할 때 새로 생긴 커밋을 merge commit 이라고 합니다.
Rebase
A 브랜치를 master 브랜치에 머지하기 전 상황에서 A 브랜치에서 c7, c8 작업을 추가로 했다고 가정하겠습니다.
A 브랜치를 master 브랜치로 rebase 해보겠습니다.
rebase 명령을 하는 순간 두 브랜치가 나뉘기 전인 공통 커밋(c4) 로 이동 후, c4 커밋부터 c8 커밋까지 (c6, c7, c8) diff 를 차례대로 만들어 임시로 저장 후 A 브랜치가 master 브랜치가 가리키는 커밋 (c5) 를 가리키게 하고 방금 저장해 놓았던 변경사항 (C6, C7, C8) 을 차례대로 적용합니다.
c6, c7, c8 을 그대로 적용하는것이 아닌 c6, c7, c8 의 변경사항과 같은 새로운 커밋을 만들어 적용합니다 .
master 브랜치로 체크아웃 후 A 를 merge 하면 c8 커밋이, c5 커밋에 기반했기 때문에 fast-forward 방식의 merge 가 일어납니다.
Merge 와 Rebase
- merge 는 두 브랜치의 최종커밋을 보고 합칩니다.
- merge 는 merge commit 이라는 commit 이 생깁니다.
- rebase 는 한 브랜치의 변경사항을 순서대로 다른 브랜치에 적용하면서 합칩니다.
- rebase 는 merge commit 을 만들지 않습니다. 커밋히스토리가 깔끔합니다.
그럼 무조건 Rebase 가 좋은가?
그건 아닙니다. rebase 는 작업내용을 임시로 저장 후 새로운 커밋을 만드는 방식입니다. 이미 원격저장소에 push 한 커밋을 rebase 하면 내용 같은 또 다른 커밋을 만들게 되는 것이고 , 그 코드를 다시 원격저장소에 push 한다면 원격저장소에는 같은 작성자, 같은 내용의 커밋이 여러개가 될 수 있어, 동료들을 혼란스럽게 할 수 있습니다. 따라서 원격저장소에 push 한 커밋은 rebase 하지 말아야 합니다.