커밋(commit)과 브랜치(branch)와 병합(merge)은 서로 깊은 연관이 있다. 개인적으로는 이 세가지는 한세트로 여겨도 될 것 같다. 하지만 이 포스트는 merge 전략이므로 커밋과 브랜치는 가볍게 필요한 만큼만 짚고 가겠다.
커밋은 의미 있는 변경 내역을 기록하는 것이다. 소스코드는 수없이 변하고 그 변경 내역을 누적해서 기록한다. 커밋 하나 하나가 점이라면 그 점이 긴 선을 이루는 것이다.
브랜치는 어느 시점의 커밋으로 부터 분기된 가지이다. 보통 맨 처음 생성된 가지를 master 또는 main 브랜치라고 한다. 새로 생성된 브랜치는 기존 커밋 흐름에서 분리되어 별도의 커밋 흐름을 생성한다.
이 서로 다른 두 브랜치를 다시 하나의 브랜치로 통합하는 것이 병합(merge)이다. 이때 고려해야 할 점이 몇가지 있다. 그중 한가지가 '서로 다르게 누적된 커밋을 어떻게 처리할 것인가?'에 대한 문제이다.
여기서 등장하는 것이 병합 전략이다. 병합을 어떻게 수행하느냐에 따라 커밋 흐름이 어떻게 유지되는지 달라진다.
Create a merge commit
각각 브랜치에 기록된 커밋을 히스토리에 그대로 남긴다. 브랜치의 생성, 커밋 기록, 병합 내역등 자세한 정보가 남기 때문에 프로젝트 흐름을 아주 상세하게 파악할 수 있다.
단점은 그만큼 히스토리가 자세하기 때문에 원하는 내역을 찾기 힘들다는 점이다. 만약 HEAD조작이 있을경우 그래프가 꼬여서 더 알아보기 힘들 수 있다.
A - B - C - F (main)
\ /
D - E (feature)
- F커밋은 C,E 두 커밋의 변경 사항을 전부 포함한다
Squash and merge
Squash 기능을 이용하여 브랜치에 기록된 커밋을 하나로 묶어 한개 커밋으로 처리하는 전략이다. Create a merge commit보다 남아있는 정보가 적기 때문에 히스토리 일부를 잃을 수 있다는 단점이 있다.
짧은 버그 수정이나 일부 변경등을 유연하게 하나로 묶어 처리하는 방식으로도 사용한다.
A - B - C (main)
\
D - E - F - G (feature)
- main 브랜치와 feature브랜치를 Squash and merge 전략대로 병합하면 D - E - F - G 커밋이 하나로 묶인다.
A - B - C - H (main)
- H커밋은 D - E - F - G커밋을 하나로 묶은 것이다.
Rebase and merge
rebase 기능을 이용하여 브랜치를 병합하는 전략이다. 히스토리의 base를 직접 옮겨서 처리하기 때문에 feature 브랜치에서 작업한 내용을 main 브랜치에서 작업한 것처럼 취급할 수 있다.
단점은 merge 커밋이 없기 때문에 어느 시점에 병합을 수행했는지 파악하기 힘들다는 점이다.
A - B - C (main)
\
D - E (feature)
- rebase를 이용하면 어느 한 브랜치의 커밋을 다른 브랜치의 끝으로 이동시킨다.
A - B - C - D' - E' (main과 feature)
- D - E의 변경사항을 포함하지만 새로운 커밋해시를 가진다. 완전히 다른 커밋이 되는 것이다.
병합 전략은 대략 이렇다. 그러면 '병합전략'이 아니라 '병합'은 어떻게 수행되는 것일까?
Fast-forward merge
단순히 HEAD만 옮기면 될 때 Fast-forward merge가 수행된다.
보통 Rebase를 설명할때 자주 언급되는데 서로 다른 브랜치가 하나의 브랜치가 되었으므로 최신 커밋이 위치한 부분으로 HEAD만 옮기면 되기 때문이다.
A - B - C - D' - E' (feature)
|
main
- rebase를 수행한 상황이다.
- main 브랜치로 전환 후 병합하면 feature의 최신 커밋이 있는 곳으로 HEAD를 이동시킨다.
A - B - C - D' - E' (main과 feature)
3-way merge
서로 다른 두 브랜치가 병합하려 할때 해당하는 둘만 비교하면 변경된 요소가 무엇인지 알 수 없다. 또는 두 브랜치가 충돌이 일어났는지 알 수 없다. 원본이 무엇인지 알 수 없는 것이다. 그래서 공통된 부모를 기준으로 변경 요소를 파악한다.
이렇게 3개 커밋(원본, 커밋A, 커밋B)을 비교해서 병합을 진행하는 것을 3-way merge라고 한다.