merge는 가장 자주 사용하는 명령 중 하나입니다. 그런데 똑같은 merge명령을 내리더라도 깃은 기존의 히스토리에 따라 다른 방식으로 병합을 진행합니다. 병합하려는 두 브랜치 모두에 변경사항이 있다면 깃은 3-way merge를 진행합니다. 둘 중 한 곳에만 변경사항이 있다면 깃은 fast-forward를 진행합니다.
본문에서는 각각의 방식에 따라 히스토리가 어떻게 달라지는지 서술하겠습니다. 보다 자세히 알고 싶다면 원본인 Pro Git 3.2 Git 브랜치 - 브랜치와 Merge 의 기초를 참고해주세요.
master브랜치에서 iss53브랜치로 merge를 시도하려는 상황입니다.
master브랜치에 별다른 변경사항이 없고 iss53브랜치에만 커밋이 추가된 상황이기 때문에, 두 브랜치를 병합하려면 master브랜치의 HEAD(각 브랜치 명은 최신 커밋을 가리키는 포인터입니다)를 iss53의 위치까지 이동시키기만 하면 됩니다.
이것을 fast-forward라고 하며 이 경우 절대로 충돌이 발생하지 않습니다.
master브랜치에서 iss53브랜치로 merge를 시도하려는 상황입니다.
아까와는 달리 master브랜치에도 커밋이 하나 추가되었습니다. 두 브랜치를 병합하려면 양쪽 브랜치에서 발생한 변경사항을 모두 더해야 합니다. 이럴 때 깃은 다음과 같이 히스토리를 정리합니다.
깃은 새로운 커밋을 하나 만든 뒤 양쪽 브랜치의 변경사항들을 차곡차곡 반영합니다. 그리고 병합의 주체가 되는 브랜치의 HEAD를 새로 만든 커밋으로 이동시키죠. 이것을 3-way merge라고 지칭합니다.
3-way merge에서는 충돌(conflict)이 발생할 수 있습니다. 두 브랜치에서 같은 곳을 수정했다면 깃의 입장에서는 어느 쪽 변경사항이 옳은 것인지 알 수 없습니다. 때문에 잠시 작업을 중지하고 병합을 시도한 사용자에게 달려와 어떤 변화를 반영해야 할 지 확인해달라고 요청하는 것이죠. 충돌이라는 어감과 달리 생각하는 것만큼 위험한 상황은 아니죠?