Git의 여러가지 Merge(병합) 방법

YB Lee·2023년 5월 30일
0

git pull 명령어

git pull 명령어는 git fetch 명령어와 git merge 명령어를 순서대로 실행하는 명령어다. git pull 명령어는 로컬 브랜치와 원격 브랜치의 이력 차이를 정확히 파악하고 있는 상황이 아니라면 함부로 실행해서는 안 된다. 가능하면 git fetch 명령어로 원격 브랜치의 이력 상태를 파악한 후 git merge 명령어로 병합하는 것이 좋다.

fast-forward 병합

새로운 브랜치 my-branch 가 main 브랜치로부터 분기된 이후 main 브랜치에 새로운 커밋이 올라오지 않았다면, my-branch 가 main 와 비교하여 최신의 브랜치라고 할 수 있다. 이런 경우 my-branch 의 변경 이력을 그대로 main 으로 가져올 수 있는데, 이를 Fast-Forward Merge 라고 한다.

병합 명령에서 --squash 옵션이 없으면 Git이 병합 전략을 판단하여 fast-forward 병합이 가능하면 ff병합을 수행한다. 또는 명시적으로 --ff-only 옵션을 줄 수 있다. (단 이때, ff병합이 불가능하면 abort 가 된다.)

Squash 병합

Squash는 여러개의 커밋을 하나의 커밋으로 합치는 것을 의미한다. Squash Merge는 병합할 브랜치의 모든 커밋을 하나의 커밋으로 Squash한 새로운 커밋을 Base 브랜치에 추가하는 방식으로 병합하는 것을 의미한다.

$ git checkout main
$ git merge --squash my-branch
$ git commit -m "squash & merge"

이때, git merge 명령어에 --squash 옵션을 사용하는 squash 병합은 병합 결과를 커밋하는 것이 아니라 변경 사항을 파일에 반영해 Staging Area에 등록된 상태로 둔다.

따라서, 명시적으로 커밋을 실행해 병합을 완료한다.

recursive 병합

my-branch 가 main 브랜치에서 분기되고, main 브랜치에 새로운 커밋이 생겼다면, my-branch 를 최신이라고 간주할 수 없다. 따라서 my-branch 와 main 을 공통 부모로 한 새로운 Merge Commit 을 생성하게된다. 이런 방법을 Recursive Merge라고 한다.

또한, Fast-Forward Merge가 가능한 상태에서 git merge 명령에 --no-ff 옵션을 주면 강제로 Merge Commit을 생성하게 할 수 있다.

recursive 전략은 3방향 병합(3-way merge) 알고리즘을 기반으로 2개 브랜치의 마지막 커밋을 병합한다.

3방향 병합(3-way merge) 알고리즘은 병합할 두 파일과 두 파일의 공통 원본 파일을 비교해 병합하는 방법이다. 3방향 병합 알고리즘에 관한 더 자세한 내용은 Wikipedia의 "Merge (version control)"를 참고한다.

리베이스

fast-forward 병합이 불가능할 때에도 --squash 옵션으로 병합을 실행하면 이력을 가지가 없는 하나의 선으로 정리할 수 있다. 이력을 한 줄로 정리하는 또 다른 방법으로 리베이스(rebase)가 있다. 그 결과는 fast-forward 병합과 유사하다.

Rebase는 무엇일까? 말 그대로 Base를 다시 설정한다는 의미이다. 그럼 Base를 어디로 다시 설정할까? my-branch 가 분기된 main 브랜치의 최신 커밋이다.

$ git checkout my-branch
$ git rebase main
$ git checkout main
$ git merge my-branch

명령 순서를 보면 알겠지만, 결과적으로 Fast-Forward Merge를 사용하는 것을 확인할 수 있다.

참고링크

https://hudi.blog/git-merge-squash-rebase/
https://d2.naver.com/helloworld/1859580

profile
Those who have a 'why' to live, can bear with almost any 'how'.

0개의 댓글