프로그래밍/devops

git merge, rebase, squash 차이

브래드 킴 2023. 1. 29. 21:42
728x90

여기서는 git으로 협업시의 merge, rebase, squash에 대한 차이와 merge전략에 대한 얘기를 하고자 한다.

 

현업에서는 회사마다 git branch전략이 제각각 이겠지만, 일반적으로는 develop(개발) -> release(운영)과 같은 형식으로 브랜치가 구성돼 있거나, 단일 main 브랜치로 운영이 된다 하더라도 협업을 할때에는 각각의 feature브랜치 만들어 작업후에 merge하는 과정을 거쳐 git에서 소스코드를 관리할 것이다.

 

예를 들어) 기능 추가/수정 시에 개발자들이 feature브랜치를 따서 개별적으로 브랜치에서 작업한 후에 develop으로 PR을 올린 이후에, 해당 PR을 merge하는 과정을 거치게 될 것이다. 충분한 테스트와 검증이 끝나면 develop에서 release로 merge를 함으로서 최종 서비스에 반영되는 과정을 거치게 될 것이다.

 

PR이후에 merge를 함에 있어 github의 3가지 옵션에 각각 어떤 차이가 있는지 살펴보도록 하자.

 

merge

branch1에서 작업을 끝낸 개발자가 develop으로 merge를 했을때 develop 브랜치는 아래와 같은 history가 남게 된다. 

merge를 시킬 때마다 merge 커밋이 남게 되어, 다소 지저분한 history가 된다는게 단점이지만 각 branch의 commit ID와 히스토리를 그대로 가지고 있어 충돌의 위험이 작다는게 가장 큰 장점일 수 있겠다.

 

rebase and merge

그러나, merge를 하지 않고 rebase를 사용하는 것의 장점으로는, 아래와 같이 merge commit이 남지 않고 깔끔한 history관리가 가능하게 된다.

 

rebase의 단점

rebase and merge의 단점으로는, 기존의 feature브랜치가 가지고 있던 commit ID와 rebase이후의 develop브랜치(공용브랜치) commit ID가 달라지게 된다. 그래서, 만약 기존의 feature브랜치를 가지고 추가적인 작업을 하여 다시 PR을 올리게 되면, 기존의 commit ID가 develop브랜치에는 존재하지 않으므로 이전에 추가했던 작업을 인식하지 못하고 마치 최초로 merge를 하는 것과 같이 그 이전의 차이까지 모두 diff를 생성하는 것을 보게 될 것이다.

 

그래서, rebase의 경우 한번 사용한 기존의 feature브랜치는 재사용이 불가능하다. 기존의 브랜치를 삭제하고, develop(공용브랜치)에서 다시 branch를 생성하여 다시 생성된 branch로 새로이 작업을 해 나가야 하는 번거로움이 생기게 될 것이다.

 

그럼에도, history가 깔끔해진다는 점에서 나는 develop브랜치를 rebase로 관리하는 것을 선호한다.

 

다만, develop브랜치에서 최종적인 release브랜치로 merge할때에는 rebase전략은 위험할수가 있다. 그래서 이때에는 commit원상복구, develop브랜치의 지속적인 사용 등을 위해서라도 기존의 commit ID를 잘 보존 할 수 있도록 일반적인 merge pull request를 사용하는 것이 좋겠다.

 

 

squash and merge

squash and merge의 경우 branch의 여러 commit을 하나의 commit으로 병합할 수 있는 방법이다.

feature 브랜치에서 develop(공용브랜치)로 PR을 올리고난 후 merge를 할때에, feature브랜치의 commit ID가 너무 많다면, 이 또한 history가 지저분해질 가능성이 있다. 그래서, 자잘한 commit 내용을 잘 정리한 후에 하나의 commit ID로 만들어내는 방법이 squash and merge라고 볼 수 있겠다. 물론 merge commit도 없다. 만약 rebase로 merge를 하게 되면, merge commit은 없겠지만 기존의 여러 commit ID를 주렁주렁 달고 merge가 되는 것을 보게 될 것이다. 

728x90