Types of Git Merge Strategies (git merge 유형)

2021. 9. 25. 23:27카테고리 없음

반응형

이 글은,, 올해 3월에 https://nurisis.medium.com 에 올렸었던 글인데, 내 medium 블로그가 블락당해서,,, 나만 읽을 수 있는 글이 되어버렸다.. 나는 죄가 없는데... 개발 글만 7개 올렸을 뿐인데.. 왜.. 장난으로 신고당한 걸까..? 어느 날부터 내 계정은 조사 중이라는 팝업이 뜨더니.. 지금까지 글을 쓸 수 없게 되었다,,, medium 측에 관련해 메일을 4통 이상 보냈지만 답은 없고,, 시간이 지나면 풀리겠지라는 희망을 갖고 임시로 티스토리에 글을 쓰기 시작했으나,, 이제는 여기에 정착해야,, 할 것 같다. 그래서 medium에 올렸던 글을 하나씩 여기로 옮겨보려고 한다. 

목차

     


     

    나를 포함한 많은 사람들이 git을 버전 관리 도구로 사용한다.

    나는 평소에 git flow 를 사용해 아래와 같은 흐름으로 브랜치 관리를 하고 있다.

    • master -> develop
    • develop -> feature/some-new-features

     

    그리고 위에서 생성한 feature 브랜치 작업을 마치면 develop 브랜치에 merge 한다. 이때, 아래 3가지 유형의 merge 전략이 존재한다. 

     

    1️⃣ Merge commit

    2️⃣ Squash and merge

    3️⃣ Rebase and merge

     

    위 3가지 유형의 차이점은, 직접 브랜치를 생성하고 merge 하는 테스트를 통해 알아보려고 한다. 

     

     

    테스트 시나리오 

    3가지 종류의 merge 전략을 테스트하기 위해, master 브랜치에서 아래 3개의 브랜치를 생성했다.

    • example/merge-commit
    • example/squash-and-merge
    • example/rebase-and-merge

     

    위의 각 브랜치에서, 3개의 변경사항을 commit 했다. 즉 각 브랜치는 아래와 같은 flow 를 갖게 된다.

    example 브랜치 생성 후, 3개의 commit 을 올렸을 때의 상태 

     

    그 후에, 각 3개의 브랜치를 각기 다른 방식으로 master 브랜치에 merge 할 것이다! 이렇게 다른 방식으로 merge 했을 때 어떤 차이들이 있는지를 알아본다. 

     

     

    TYPE 1. Create a merge commit 

    한 브랜치와 다른 브랜치의 모든 변경 이력들을 합치는 방법. 또한, 머지 시 merge commit 이 추가된다. (말은 어렵다. 아래 예시로 이해하자!)

     

    예를 들어, master 브랜치에 위에서 만든 example/merge-commit 를 merge commit을 생성해 머지하고자 한다.

    이때의 git history는 아래와 같이 같고, 그림에서 보듯이 주황색의 merge commit 이 생성된다.

    merge commit flow 

     

    흠, 그래서 뭐 모든 변경 이력들이 합쳐진다는데 무슨 소리야?라는 생각이 들 텐데, 실제로 머지를 했을 때의 history를 직접 보자!

    우선, 위에 테스트 시나리오에서 example/merge-commit 에 3개의 commit을 푸시했었다. 아래와 같이.

    example/merge-commit 의 commit history

     

    그리고, 이를 master에 merge 한 후의 master history는 아래와 같다. merge commit(94718cb) 이 생겼고, 그 아래로 example/merge-commit의 commit history까지 같이 추가되었다!!!!!

    merge commit 이후 master 의 commit history

     

    그래서 어떻게 해?

    베이스 브랜치(위 예시에서는 master)에 checkout 한 뒤, 아래 명령어를 실행! 

    $ git merge { merge 하려고 하는 브랜치명 }

    만약, 두 브랜치가 fast-forward 관계라면,  --no-ff 를 써줘야 merge commit을 생성할 수 있다. 

    $ git merge --no-ff { merge 하려고 하는 브랜치명 }

     

    즉, 예시! 만약 내가 example/merge-commit 브랜치를 master 브랜치로 merge commit 을 생성해 merge 하고 싶다! 

    $ git checkout master
    $ git merge example/merge-commit

     

     

     

    TYPE 2. Squash and merge

    Merge commit 과 달리 여러 commit들이 반영된 브랜치를 머지하더라도, 여러 commit이 모두 반영된 새로운 commit 하나만 추가된다!

    예를 들어, master 브랜치에 위에서 만든 example/squash-and-merge 를 squash and merge 하고자 한다. 

    square and merge

     

     

    실제로 머지를 했을 때의 history를 직접 보자! 우선, 위에 테스트 시나리오에서 example/squash-and-merge 3개의 commit을 푸시했었다. 아래와 같이.

    example/squash-and-merge branch 의 commit history

     

    그리고, master에 squash and merge 하면, master 브랜치의 commit history는 아래와 같다.

    오, 정말 example/squash-and-merge 브랜치에서 생성한 3개의 commit 은 보이지 않고, Squash merge to master 커밋만 추가된다. 

    squash and merge 후 master 의 commit history

     

    그리고 "Squash merge to master"라는 이름의 새 커밋을 보면 example/squash-and-merge 브랜치에 추가된 세 개 커밋의 변경사항들이 하나의 커밋에 추가된걸 볼 수 있다.

     

    다 이해하고 보면, 왜 squash라는 이름이 붙었는지 이해가 간다. 여러 개의 커밋들을 squash(짓눌러서) 하나의 커밋으로 만들어 머지하니까!

     

    그래서 어떻게 해?

    베이스 브랜치(위 예시에서는 master)에 checkout 한 뒤, 아래 명령어를 실행!

    git merge --squash { branch to merge }

     

    즉, 위의 예시에서는 이렇게!

    $ git checkout master
    $ git merge --squash example/squash-and-merge

     

     

     

    TYPE 3. Rebase and merge

    요 아이는 위 2개와는 다르게 merge 했다는 커밋이 별도로 추가되지 않고, 머지하는 브랜치의 커밋 내역들이 그대로 추가된다.

     

    rebase and merge

     

     

    실제로 머지를 했을 때의 history를 직접 보자! 우선, 위에 테스트 시나리오에서 example/rebase-and-merge 3개의 commit을 푸시했었다. 아래와 같이

     example/rebase-and-merge 브랜치 commit history

     

    그리고, master에 rebase and merge 하면, master 브랜치의 commit history는 아래와 같다.

    머지되면서 생긴 별도의 커밋 없이, example/rebase-and-merge 의 커밋 내역만 들어간 것을 볼 수 있다. 

    rebase merge 후 master 브랜치의 commit history

     

    그래서 어떻게 해?

    베이스 브랜치(위 예시에서는 master)에 checkout 한 뒤, 아래 명령어를 실행

    $ git checkout { merge 하려는 브랜치 }
    $ git rebase { rebase 하려는 브랜치 }
    
    $ git checkout { rebase 하려는 브랜치 }
    $ git merge { merge 하려는 브랜치 }

     

    즉, 위의 예시에서는 이렇게!

    $ git checkout example/rebase-and-merge
    $ git rebase master
    
    $ git checkout master
    $ git merge example/rebase-and-merge

     

     

     

    반응형