11: 브랜치 합치기(git merge)

3 분 소요

이번 글에서는 두 개의 브랜치를 합치는 git merge에 대해 배우도록 하겠습니다. 브랜치를 합치기 위해서는 주가 될 브랜치로 이동한 후, 합치고자 하는 브랜치 이름을 이용하여 명령어를 실행해주시면 됩니다:

$ git checkout master    # master 브랜치로 이동
$ git merge topic    # master 브랜치에서 topic 브랜치를 merge 

이제부터 두 가지 종류의 merge에 대해 배웁니다.

fast-forward merge

master 브랜치에서 다음과 같이 작업을 하고 있다고 가정합시다:

이때, 급하게 수정해야 할 버그가 생겨 hotfix 브랜치를 만들어 버그를 수정했습니다. (이때, master 브랜치에서 수정하지 않고 hotfix라는 브랜치를 따로 만드는 이유를 한 번 생각해보세요):

이후, 수정 내역을 반영해주기 위해 master 브랜치에서 hotfix 브랜치를 merge 해줍니다. 이런 경우는 master가 가리키고 있는 커밋에 덧붙여서 새로운 커밋들이 생긴 것이므로, 두 브랜치를 합치기 위해서는 master 브랜치를 hotfix 브랜치로 간단히 옮겨주면 됩니다:

fast-forward merge를 성공했을 경우, Fast-forward라 표시됩니다.

이런 방식의 merge를 왜 하는지 의문이 드신다면 git 브랜치 관리하기를 읽어보시기 바랍니다.

3-way-merge

이번에는 갈라진 두 개의 브랜치를 merge하겠습니다. 갈라진 두 브랜치를 합쳐주기 위해서는 merge하고자 하는 두 브랜치가 가리키는 커밋들과 공통의 조상 커밋(즉, 갈라지기 시작하는 커밋)을 이용하여 merge를 진행하고, 이를 3-way-merge라 합니다. merge가 완료될 경우, 저희가 원하는 브랜치의 모습입니다:

  • merge 이전

  • merge 이후

master 브랜치에서 merge를 할 경우, 위의 그림처럼 master 브랜치의 포인터가 이동했습니다. 반대로 snu 브랜치에서 merge를 할 경우, master 브랜치의 포인터는 제자리에 있고 snu 브랜치의 포인터가 이동합니다.

3-way-merge가 성공적으로 일어난 경우, Merge made by the ‘recursive’ strategy라 표시됩니다.

merge conflict

merge 연습을 같이 해봅시다. 현재 브랜치는 위의 3-way-merge의 사진과 같이 두 개의 브랜치로 갈라진 상황입니다. 각 커밋의 내용과 차이점은 다음과 같습니다:

이 상황은 merge를 굳이 할 필요 없지만, 연습을 위해 해봅시다. master 브랜치에서 snu 브랜치를 merge를 진행합니다. 그럼 다음과 같은 메세지가 나올 것입니다:

$ git branch.   # 현재 브랜치 확인
* master
  snu
$ git merge snu
CONFLICT (content): Merge conflict in 자기소개서.txt
Automatic merge failed; fix conflicts and then commit the results.

해석해보니, 자동 merge가 실패했으니, 충돌 부분을 수정하고 결과를 다시 커밋하라고 합니다. 충돌이 일어난 이유는 두 브랜치에서 자기소개서 4번 문항의 내용이 서로 다르기 때문입니다. 이와 같이 같은 부분에 서로 다른 내용이 있을 경우 merge conflict가 발생합니다. 이는 직접 충돌난 부분을 수정해주어야 합니다.

충돌을 수정하기 위해 자기소개서.txt 파일을 열어보면 다음과 같이 뜹니다:

$ cat 자기소개서.txt    # 자기소개서.txt 파일 내용 출력
1. 고등학교 재학 기간 중 학업에 기울인 노력
열심히 공부했습니다.
2. 고등학교 재학 기간 중 의미 있었던 교내 활동
농구 동아리 활동입니다.
3. 학교 생활 중 배려, 나눔, 갈등 관리를 실천한 사례
봉사활동을 주 2회 했습니다.
<<<<<<< HEAD
4. 과학기술인이 가져야 할 자세
포기하지 않는 자세
=======
4. 영향을 미친 책
끌리는 리더의 조건
>>>>>>> snu

자기소개서 3번 문항까지는 내용이 제대로 작성되어 있습니다. 이와 같이 충돌이 일어나지 않은 부분에는 아무런 변화가 없습니다.

충돌이 일어난 부분은 <<<<<<< 와 =======, 혹은 =======와 >>>>>>> 사이에 표시됩니다. <<<<<<<와 ======= 사이에 표시된 내용은 merge를 실행한 브랜치에 있는 내용, 즉 HEAD가 가리키고 있는 내용입니다. 반대로, =======와 >>>>>>> 사이에 표시된 내용은 merge를 하고자 하는 브랜치, 즉 sad 브랜치의 내용입니다. 이 표시들을 기반으로 원하는 것을 선택하여 수정을 마친 후 충돌이 일어난 파일을 커밋해주면 merge가 완성됩니다. (표시들은 모두 없애줍니다.)

저는 다음과 같이 수정했습니다:

$ cat 자기소개서.txt
1. 고등학교 재학 기간 중 학업에 기울인 노력
열심히 공부했습니다.
2. 고등학교 재학 기간 중 의미 있었던 교내 활동
농구 동아리 활동입니다.
3. 학교 생활 중 배려, 나눔, 갈등 관리를 실천한 사례
봉사활동을 주 2회 했습니다.
4. 과학기술인이 가져야 할 자세
포기하지 않는 자세

수정을 완료했으면 커밋을 완료합시다:

$ git add 자기소개서.txt 
$ git commit
[master 4aa5625] Merge branch 'snu'    # 성공적으로 수정했을 경우 출력 메세지

충돌을 해결한 후의 커밋 메세지는 다음과 같이 작성합니다. 어떻게 충돌을 해결했고 좀 더 확인해야 하는 부분은 무엇이고 왜 그렇게 해결했는지에 대해서 자세하게 기록합니다. 자세한 기록은 나중에 이 Merge 커밋을 이해하는데 도움을 줍니다.

git log ––graph

--graph 명령어를 사용하시면 브랜치를 그래프로 볼 수 있습니다. git log --oneline --decorate --graph --all 명령어를 사용하면 갈라져 나온 다른 브랜치들도 확인하실 수 있습니다:

댓글남기기