[Git] git merge, git rebase

Date:     Updated:

카테고리:

태그:

출처 글 👉 https://victorydntmd.tistory.com/78?category=682764

이 글은 victorydntmd님 블로그의 git merge 포스트를 거의 대부분 참고한 글입니다. git branchgit merge를 이 분 블로그에서 공부했습니다. 이해가 쏙쏙 잘 되게 설명을 너무 잘해주셔서.. ㅠㅠㅠ 출처는 이 분 블로그임을 밝히며 개인적인 필기를 남기기 위한 용도로 이 분의 블로그 글을 정리하는 것임을 밝힙니다. git merge 설명은 링크 남긴 이 분의 블로그에서 보시는 것을 추천드립니다! (훨씬 설명 잘 되어있음!!!)


merge

merge 👉 2 개의 브랜치를 하나로 합치는 것. 현재 위치한 브랜치를 기준으로 병합된다.

  • 2 개의 브랜치를 합칠 때 만약 두 브랜치가 같은 파일의 같은 곳을 수정했다면 충돌(merge conflict)가 발생한다. 👉 merge의 중요한 이슈.
    • merge conflict 가 발생하면 관계자들이 상의하여 직접 코드를 수정하여 충돌을 해결해야한다.
    • 애초에 merge conflict 가 발생하지 않도록 즉 작업 내용이 겹치지 않도록 분담하는게 좋다.

git merge 브랜치이름 👉 현재 위치한 브랜치에 해당 브랜치를 가져와 merge 한다.


merge conflict

<<<<<< HEAD
블라블라
=======
뫄뫄뫄뫄
>>>>>> FOO

병합시 충돌이 일어났다면 병합을 진행하지 않고 이렇게 현재 위치 중인 브랜치의 내용 (<<<<<< HEAD)과 병합하려는 대상인 브랜치의 (>>>>>> 브랜치이름)의 내용의 다른 점을 보여준다. 팀원들은 이걸 보고 어떻게 병합을 할지 상의하여 코드를 고쳐 충돌을 해결한 후 병합해야 한다.


Fast-Forward 방식으로 병합

master 브랜치를 부모로 하는 test 브랜치를 분기 생성했다고 가정해보자. 현재 test 브랜치의 작업물들은 master 브랜치의 작업물들의 내용과 역대 commit 내역이 동일한 상태일 것이다. 그 상태에서 test 브랜치의 작업물에 코드 한 줄을 추가하여 commit 했다고 가정해보자.

git checkout -b test
git add
git commit -m "test"

git checkout master
git merge test

test 브랜치는 master 브랜치의 커밋 내역을 전부 다 포함하고 있고 그 상태에서 test 브랜치가 커밋을 한번 더 했기 때문에, test 브랜치가 master 브랜치 보다 더 최신 버전이고 앞선다고 볼 수 있다. 따라서 master 브랜치를 가져와 test브랜치에 병합한다. 두 브랜치를 병합시 커밋 내역이 더 앞서가고 있는 브랜치를 기준으로 병합하는 것을 Fast-forward 방식 병합이라고 한다.(뒤쳐져 있는 master를 빨리 감기하여 통합시킴)

image

  • 이렇게 분기된 브랜치가 부모 브랜치의 커밋 내역을 모두 포함할 수 있다면, 즉 부모 브랜치가 분기 이후 자신만의 커밋을 진행한 것이 없었다면, 위와 같이 통합할 수 있다. 위와 같이 통합되는 방식을 Fast-forward 라고 한다.
    • master 브랜치의 커밋 내역은 A -> B 에서 병합 후 A -> B -> C -> D -> E 가 되었다. 빨리 감기 되어 껑충 뛴 셈.
  • 현재의 가지는 master이며 이 가지는 test로도, master로도 불릴 수 있는 가지가 되었기 때문에 두 브랜치가 중복되므로 test 로컬 브랜치는 삭제해주는 것이 좋다. (push 한 후 삭제하면 원격 저장소에 test 커밋 내역은 보존할 수 있기 때문에 문제 없고 로컬 브랜치로서의 test만 삭제하면 된다.)


Non Fast-Forward 방식으로 병합 (👉 Merge Conflict 발생 우려)

통합 하려는 두 브랜치가 서로 다른 커밋 내역을 가지고 있을 경우 (서로 포함 불가능한) Non Fast-Forward 방식으로 병합할 수 밖에 없다. 서로 다른 커밋 내역을 가지고 있기 때문에, 그리고 동일한 부분을 다르게 코딩했을 가능성도 있기 때문에 병합할 때 충돌이 발생할 수 있다.

Merge Conflict 👉 동일한 코드를 서로 다른 내용으로 바꿨다면 Merge시 어떻게 해야할지 알 수 없기 때문에 충돌이 발생한다. 이럴땐 팀원들이 서로 충돌되는 두 코드를 어떻게 합칠지 의논 후 수동적으로 직접 해당 코드를 Merge 하여야 한다. 충돌 문제가 해결 되어야 Git 에서 Merge를 해줄 수 있다. 애초에 이런 작업을 최소화 하기 위해 최대한 팀원들이 맡은 작업이 서로 겹치지 않도록 해야 한다.

Merge Commit

분기 후 부모 브랜치에서도 부모 브랜치 본인의 커밋 내역들이 진행됐을 경우에는 Fast-Forward 방식으로 병합할 수 없다. 부모 브랜치의 커밋 내역을 자식 브랜치가 모두 포함할 수가 없기 때문이다.

image

이런 경우에는 Fast-Forward 방식으로 병합 되지 않는다.

image

Non Fast-Forward 방식 👉 두 브랜치를 하나로 합친 새로운 커밋을 진행한다.

  • 두 브랜치의 최근 상태(커밋 G, 커밋 E)를 합친 결과물을 만든 후 이를 새롭게 H 로 커밋한다. 이를 병합 커밋이라고 한다.
  • Non Fast-Forward 이기 때문에 병합 후 부모 브랜치는 자식 브랜치만의 커밋 내역을 품지 못한다.
    • master 브랜치에서 병합을 했다면
      • master 브랜치의 커밋 내역은 A -> B -> F -> G -> H 가된다. master 브랜치의 커밋 내역으로서 C -> D -> E 커밋 내역은 품지 않는다. (다만 커밋 H 에 C -> D -> E 을 거쳐 완성된 E 커밋 결과물이 반영이 되어서 통합 되있을 것이다!)
      • test 브랜치의 커밋 내역은 A -> B -> C -> D -> E -> H 가 된다.
    • 두 브랜치가 동일해졌으므로 나머지 하나인 test 로컬 브랜치는 삭제해 주는 것이 좋다. (test의 커밋 내역을 원격 저장소에 보존하고 싶다면 push 후 로컬 test 삭제하기)
  • Fast-Forward 방식은 Merge Commit 이 생략된다. 앞선 브랜치로 빨리 감기 될 뿐이다.


rebase 로 Merge

rebase는 말그대로 브랜치의 base (부모 브랜치)를 바꾸는 작업이다. rebase로 부모 브랜치를 바꿔주어 브랜치를 통일한 후 Merge 하는식으로 작업한다.

image

Merge Commit 을 만드는 방식으로 두 브랜치를 Merge 시킨 경우다. 이 같은 경우 위와 같이 두 브랜치의 이력이 남게 된다. 이력 조작을 하지 않고 그냥 했던 그대로 정확한 이력을 남기고 싶은 경우에는 괜찮지만 이런 커밋 이력이 많아지면 복잡해진다. 두 브랜치를 이미 통합했음에도 불구하고 A ->B -> F 라는 이력도 있고.. A -> B-> C-> D -> E -> F 라는 이력도 남는 것이기 때문에 복잡하다. 두 브랜치를 통합할 때, 이런 커밋 이력들 또한 하나의 가지로 통일한다면 더 보기 좋을 것이다.

image

git rebase 브랜치 이름 👉 현재 브랜치를 base 즉, 부모 브랜치를 해당 브랜치로 바꾼다.

1️⃣ git rebase master (현재 브랜치 test)

test 브랜치의 부모 브랜치를 master 브랜치로 바꾸었다. 두 브랜치가 한 줄로 연결되었다. test 브랜치는 master 브랜치 뒤에 위치하게 되었으므로 test 브랜치의 커밋 이력들은 각각 master 브랜치의 최신 커밋인 F 커밋와 Merge 되어 새로운 커밋 이력 C’ D’ E’ 가 되어서 master 뒤에 붙게 된다.

  • master 이력 👉 A -> B -> F
  • test 이력 👉 A -> B -> F -> C’ -> D’ -> E’

2️⃣ git merge master

mastertest를 merge 하면, master보다 test가 더 최신이고 앞서 있고, testmaster의 커밋 이력을 다 품을 수 있기 때문에 (1️⃣에서 rebase 했기 때문에) Fast-Forward 방식의 merge 되어 mastertest와 동일한 커밋 이력을 갖게 된다. A -> B -> F -> C’ -> D’ -> E’

rebase 와 merge 의 차이

  • merge만 하기 (merge commit 생성)
    • 변경 내용의 이력이 있는 그대로 모두 남기 때문에 정확하지만 이력이 복잡해진다. 여러 줄기에 제각각 남아서.
  • rebase로 한 줄로 만든 후에 merge 하기 (한 줄기로 만든 후 fast-forward merge)
    • 커밋 이력이 한 줄기로 착착 보기 좋게 정리되는 장점이 있다.
    • 다만 정확한 커밋 이력을 남겨야할 필요가 있을 땐 사용 X

커밋 이력 조작하기

참고하기 https://victorydntmd.tistory.com/279?category=682764



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Git 카테고리 내 다른 글 보러가기

댓글 남기기