[Git] 브랜치 병합(Merge)과 리베이스(Rebase)

병합 (Merge)

  • 병합 커밋 생성 및 포인터 이동: no fast-forward
  • 병합 커밋 생성 없이 포인터만 이동: fast-forward
  • 병합의 결과를 별도의 새로운 커밋으로 생성하고 포인터 이동: three-way-merge


1. no fast-forward

병합 대상 브랜치(분기된 브랜치)가 분기 전 병합 기준 브랜치(현재 체크아웃한 브랜치)의 커밋에 기반한 브랜치인 경우 병합 대상 브랜치에는 작업에 대한 커밋 이력만을 남기고 병합 기준 브랜치에는 모든 작업 이력이 담긴 병합 커밋을 새로 생성한다.

Git Merge - no fast-forward


no-fast-fotward 병합은 병합 전 병합 대상 브랜치에서 생성된 모든 커밋들을 하나의 커밋으로 병합 기준 브랜치에 반영한다. 병합하려는 브랜치의 개수 만큼 병합 커밋이 생성된다.


2. fast-forward

브랜치 분기 이후 병합 대상 브랜치의 커밋이 분기 전 병합 기준 브랜치의 커밋에 기반한 브랜치이며, 병합 기준 브랜치에는 분기 이후의 커밋이 없는 경우 단지 병합 기준 브랜치의 포인터를 병합 대상 브랜치의 최신 커밋으로 이동시킨다.

브랜치 B는 브랜치 A로부터 분기한 브랜치이고, 브랜치 B를 브랜치 A에 병합 시 브랜치 B가 가리키는 커밋이 분기 전 브랜치 A의 커밋 기반이면 병합 과정 없이 단지 브랜치 A의 포인터를 최신 커밋(브랜치 B의 커밋)으로 이동시킨다.

Git Merge - fast-forward


병합 기준 브랜치에 분기 이후의 커밋이 존재하는 경우 해당 커밋을 모두 병합 대상 브랜치의 커밋으로 반영한다.

fast-forwrad 병합은 병합 커밋을 생성하지 않는다.


3. three-way merge

각 브랜치가 가리키는 커밋 두 개와 두 브랜치의 공통 조상 커밋 하나를 사용하여 단순하게 병합한다.

단순히 브랜치 포인터를 최신 커밋으로 옮기는 것이 아니라 병합의 결과를 별도의 새로운 커밋으로 생성함으로써 병합 기준 브랜치가 새로 생성된 커밋을 가리키도록 포인터를 이동시킨다.

Git Merge - three-way merge


리베이스 (Rebase)

리베이스란 브랜치의 변경된 사항을 패치(patch)로 만들고 다른 브랜치에 적용시키는 또다른 방법이다.

리베이스를 사용하면 한 브랜치에서 변경된 모든 사항을 다른 브랜치에 적용시킬 수 있다. 변경사항이 적용된 새로운 커밋을 만들고 병합 대상 브랜치가 가리키게 한 후 병합 기준 브랜치로 돌아가 fast-forward 병합을 수행한다.

Git Merge - rebase


리베이스는 한 브랜치의 변경사항을 순서대로 다른 브랜치에 적용하면서 합치는 것이고, 병합은 두 브랜치의 최종 결과만을 가지고 합치는 것이다.


어떤 병합 방법을 선택해야 하는가

작업 이력을 관리하는 워크플로우나 브랜치 전략에 따라 병합 방법을 적절히 선택하는 것이 좋다. 작업 내역을 단기적으로 병합하고 브랜치를 미사용 및 삭제하는 단기 작업 브랜치의 경우 커밋 내역을 병합 기준 브랜치의 것으로 보이도록 하는 것이 이력 관리 측면에서 더 낫다고 판단된다면 fast-forward 병합이 적절하다. 반면 작업 내역을 주기적으로 병합하고 브랜치를 유지하는 장기 브랜치의 경우 병합을 하나의 큰 작업 반영 이력으로 보고 이를 병합 기준 브랜치에 하나의 단위로 반영하는 것이 더 낫다고 판단된다면 no-fast-forward 병합이 적절하다.

병합 방법에 따라 작업 이력을 되돌리는 방법에도 차이가 나게 된다. fast-forward 병합을 사용한 경우 병합 전으로 작업 이력을 되돌리기 위해서는 커밋 별 작업 내역을 살펴본 후 브랜치의 첫 커밋을 확인해야 한다. 반면 no-fast-forward 병합을 사용한 경우 병합 커밋 바로 이전 커밋으로 되돌리기를 수행하면 된다.


참조

Comments