[Git] git merge, git rebase
카테고리: Git
이 글은 victorydntmd님 블로그의 git merge
포스트를 거의 대부분 참고한 글입니다. git branch
와 git 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
를 빨리 감기하여 통합시킴)
- 이렇게 분기된 브랜치가 부모 브랜치의 커밋 내역을 모두 포함할 수 있다면, 즉 부모 브랜치가 분기 이후 자신만의 커밋을 진행한 것이 없었다면, 위와 같이 통합할 수 있다. 위와 같이 통합되는 방식을 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 방식으로 병합할 수 없다. 부모 브랜치의 커밋 내역을 자식 브랜치가 모두 포함할 수가 없기 때문이다.
이런 경우에는 Fast-Forward 방식으로 병합 되지 않는다.
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 하는식으로 작업한다.
Merge Commit 을 만드는 방식으로 두 브랜치를 Merge 시킨 경우다. 이 같은 경우 위와 같이 두 브랜치의 이력이 남게 된다. 이력 조작을 하지 않고 그냥 했던 그대로 정확한 이력을 남기고 싶은 경우에는 괜찮지만 이런 커밋 이력이 많아지면 복잡해진다. 두 브랜치를 이미 통합했음에도 불구하고 A ->B -> F 라는 이력도 있고.. A -> B-> C-> D -> E -> F 라는 이력도 남는 것이기 때문에 복잡하다. 두 브랜치를 통합할 때, 이런 커밋 이력들 또한 하나의 가지로 통일한다면 더 보기 좋을 것이다.
git rebase 브랜치 이름
👉 현재 브랜치를 base 즉, 부모 브랜치를 해당 브랜치로 바꾼다.
1️⃣ git rebase master (현재 브랜치 test
)
test
브랜치의 부모 브랜치를 master
브랜치로 바꾸었다. 두 브랜치가 한 줄로 연결되었다. test
브랜치는 master
브랜치 뒤에 위치하게 되었으므로 test
브랜치의 커밋 이력들은 각각 master
브랜치의 최신 커밋인 F 커밋와 Merge 되어 새로운 커밋 이력 C’ D’ E’ 가 되어서 master
뒤에 붙게 된다.
master
이력 👉 A -> B -> Ftest
이력 👉 A -> B -> F -> C’ -> D’ -> E’
2️⃣ git merge master
master
와 test
를 merge 하면, master
보다 test
가 더 최신이고 앞서 있고, test
는 master
의 커밋 이력을 다 품을 수 있기 때문에 (1️⃣에서 rebase 했기 때문에) Fast-Forward 방식의 merge 되어 master
는 test
와 동일한 커밋 이력을 갖게 된다. A -> B -> F -> C’ -> D’ -> E’
rebase 와 merge 의 차이
merge
만 하기 (merge commit 생성)- 변경 내용의 이력이 있는 그대로 모두 남기 때문에 정확하지만 이력이 복잡해진다. 여러 줄기에 제각각 남아서.
rebase
로 한 줄로 만든 후에merge
하기 (한 줄기로 만든 후 fast-forward merge)- 커밋 이력이 한 줄기로 착착 보기 좋게 정리되는 장점이 있다.
- 다만 정확한 커밋 이력을 남겨야할 필요가 있을 땐 사용 X
커밋 이력 조작하기
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기