git merge 4가지 방법 정리



공부 기록을 git push 했는데, 계속 이전에 쓰던 계정으로 github에 올라가서 한참을 고생했다. 알고보니 git config –global user.email이 이전 이메일이었는데, github에는 그 이메일 주소를 통해, 옛날에 만들어 놓은 github 계정을 contributor로 만들어 놓았던 것이었다.

아무튼 그래서 commit 삭제하는 법도 알게되고 했는데, 이번 글에서는 git merge에 대해서 써보려고 한다. 결국 git이 어려운게, 이 merge가 어려워서인 듯하다.

merge에는 여러 종류가 있는데, 하나 하나 정리해보려고 한다.

1. fast-forward merge

fast-forward merge기존 master 브랜치에 새로운 커밋이 없으면서, 동시에 기존 master 브랜치에서 뻗어 나온 새로운 branch에만 commit이 있을 때 적용이 되는 merge이다.

그러면 master branch에 있던 포인터가 그냥 그대로 자기 것인것 마냥 새로운 브랜치의 커밋을 가르키게 된다. 즉, 사실상 merge가 아니다. 합친게 아니니까. 그냥 새로운 브랜치를 master 브랜치인 것처럼 써버리겠다는 것이다.

git switch master  -> 마스터 브랜치로 이동
git merge new -> 새로운 브랜치 병합 (fast-forward)
git branch -d new -> 병합이 끝난 후 새로운 브랜치 삭제


이러한 fast-forward가 싫고 진짜 merge가 하고 싶다면, git merge –no-ff <브랜치명> 을 하면 된다.

2. 3-way merge

일반적인 merge 상황이다. 기존 master브랜치에서도 추가적인 커밋이 있었고, 그전에 뻗어나온 새로운 브랜치에서도 commit을 한 후에 merge를 진행하는 것이 3-way merge이다.

conflict가 없을 때

같은 파일에서 기존 master브랜치와 새로운 new브랜치에서 서로 다른 파일에 대해 작업했다면 conflict가 나지 않는다. 이때는 별 부담없이 merge 하면 된다.

$ git switch master : 마스터 브랜치로 이동
$ git merge new : 새로운 브랜치 병합
$ git branch -d new : 새로운 브랜치 병합 후 삭제



conflict가 있을 때

한편, 같은 파일에서 서로 변경사항이 있다면 conflict가 발생하게 된다. git 프로그램 입장에서는 A에서도 변경사항이 생기고 B에서도 변경사항이 생겼는데, 어떤 변경 사항으로 합칠 건지를 물어보는 것이다.

$ git switch master : 마스터 브랜치 이동
$ git merge new : 새로운 브랜치 병합

=> 충돌 발생!!


충돌이 발생하면, VS code에서는 친절하게 어디가 충돌이 났는지 보여준다. 혹은 git status를 입력하면 충돌이 일어난 파일을 확인할 수 있다.

git merge 4가지 방법 정리


여기서 쿨하게 하나 고르면 된다. 그렇게 conflict를 해결했다면 새로 커밋을 만들어 줘야 한다.

$ git add .
$ git commit -m '커밋 해결 등'



3. rebase & merge

여기부터는 살짝 응용 및 심화 단계다. 3-way merge를 하거나 fast-forward하면 merge는 다 된다. 그럼에도 rebase & merge를 사용하는 이유는 ‘commit’이 너무 지저분해 지는 것을 막기 위해서다.

3 way merge를 하게 되면, 병합되는 브런치에서 작업했던 commit들이 전부 남게 된다. 하지만 어차피 삭제할 건데 굳이 남겨둬야할까? 이렇게 지저분하게 commit을 남기지 않기 위해 rebase를 한 후에 merge를 하면 된다.

rebase는 새로운 브랜치에서 작업했던 커밋들을, 특정 브랜치(대표적으로 master브랜치)의 최신 상태에서 시작한 것처럼 만들어 버린다. 이름부터가 re(다시) base(기반을 정하다)니깐 말이다.

그런 다음 병합을 하게되면 fast-forward가 적용되기에 깔끔하게 merge가 된다.

$ git switch new : 새로운 브랜치로 이동
$ git rebase master : 마스터 브랜치의 최신 상태로 rebase

$ git switch master : 마스터 브랜치 이동
$ git merge new : 새로운 브랜치 병합(fast-forward)


한편 rebase의 단점은, 새로 만든 브랜치가 master 브랜치의 최신 상태와 confilct가 많게 되면 그걸 다 수정해야 한다는 것이다…

충돌이 났다면???? 일단 충돌을 해결함.

$ git add . : 충돌 해결할 파일을 staging area에 올려야됨. 그래야 git이 충돌이 해결됐다는 걸 알게됨 

$ git rebase --continue : 리베이스 계속 진행.


4. squash and merge

앞서 rebase & merge가 커밋을 깔끔하게 관리하기 위한 기술인 만큼 squah & merge도 commit을 깔끔하게 만들어주는 기술이다.

squash가 으깨버리다라는 의미가 있는 것처럼, squash and merge는 새로운 브랜치에서 만든 커밋을 진짜 으깨버린다. 그냥 3 way merge를 하기 위해 새로 만든 브랜치를 master브랜치와 merge한다면, 새로 합쳐진 브랜치의 commit도 다 남게 된다. 그럼 결국 지저분하게 commit 기록이 덕지 덕지 남는다.

이때 squash & merge를 사용하게 되면, 병합되는 브랜치의 커밋을 합쳐버린 새로운 커밋만 마스터에 남길 수 있게 된다.(물론 브랜치는 지워야 깔끔하다)

$ git switch master : 마스터 브랜치로 이동

$ git merge <브랜치명> --squash : merge 평소처럼 쓰고 뒤에 --squash붙이기

$ git commit -m 'squash된 커밋 명' 

여기서 add는 안해도 되나 궁금했는데, squash를 하게 되면 병합되는 브랜치에 있던 커밋 내용들이 staging area에 자동으로 다 올라오게 된다고 한다. 그래서 그냥 commit만 새로 하면 된다.

CATEGORIES:

Tags:

No Responses

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다