-
[Git Branch] (6) 브랜치 병합하기Git&GitHub/Git Branch 2022. 5. 18. 15:22728x90
[브랜치 병합하기]
만들어진 각 브랜치에서 작업을 하다가 어느 시점에서는 브랜치 작업을 마무리하고 기존 브랜치와 합해야합니다. 이것을 '브랜치 병합(merge)'이라고 합니다. 브랜치와 브랜치를 병합하다보면 여러 상황이 생길 수 있는데 각 상황마다 병합하는 방법을 알아보겠습니다. 그리고 병합하면서 브랜치 사이에 충돌이 있을 때 해결하는 방법도 함께 살펴봅시다.
<서로 다른 파일 병합하기>
브랜치 병합은 처음 공부하기에는 까다롭기 때문에 새로운 저장소를 만들어서 필요한 브랜치와 커밋만 사용해 연습해보겠습니다.
1. 터미널 창을 열고 홈 디렉터리로 이동합니다. manual-2라는 깃 저장소를 만들텐데, git init 다음에 디렉터리 이름을 입력하면 새로운 디렉터리를 만들고 저장소를 초기화하는 과정을 한꺼번에 처리할 수 있습니다. manual-2 디렉터리로 이동한 후 ls -al 명령을 사용하면 .git/ 디렉터리가 만들어진 것을 확인할 수 있습니다.
$ cd ~
$ git init manual-2
$ cd manual-2
$ ls -al
2. 빔에서 work.txt 파일을 만들고 '1'이라는 내용을 입력한 후 저장하세요 그리고 'work 1'이라는 커밋 메시지와 함께 커밋합니다.
$ vi work.txt <- 만들고 '1' 입력하고 저장
$ git add work.txt
$ git commit -m "work 1"
3. 이제 'o2'라는 브랜치를 만들어 보겠습니다.
$ git branch o2
4. 현재 master 브랜치에 master.txt라는 파일을 하나 더 만들겠습니다. 빔에서 'master2'라는 내용을 입력하고 저장합니다.
그리고 'master work 2'라는 메시지와 함께 커밋하세요
$ vi master.txt <- master.txt 파일 생성후 'master 2' 입력후 저장
$ git add master.txt
$ git add -m "master work 2"
5. 이제 o2 브랜치로 체크아웃 합니다.
$ git checkout o2
6. o2 브랜치에서 o2.txt라는 파일을 만들고 'o2 2'라는 내용을 저장합니다. o2.txt는 'o2 work 2'라는 메시지와 함께 커밋하세요
$ vi o2.txt
$ git add o2.txt
$ git commit -m "o2 work 2"
7. git log 명령을 사용해서 현재 커밋의 상태를 확인해봅시다. 커밋 'work 1'은 master 브랜치와 o2 브랜치가 똑같이 가지고 있습니다. 그 다음으로 master 브랜치에는 'master work 2' 커밋이 생겼고 o2 브랜치에는 'o2 work 2' 커밋이 생겼습니다.
$ git log --oneline --branches --graph
8. o2 브랜치에서 작업이 다 끝났다고 가정하고, o2 브랜치의 내용을 master 브랜치로 병합해 보겠습니다. 브랜치를 병합하려면 먼저 master 브랜치로 체크아웃해야합니다.
$ git checkout master
9. 브랜치를 병합하려면 git merge 명령 뒤에 가져올 브랜치 이름을 적습니다. master 브랜치에 o2 브랜치를 가져와 병합하려면 다음과 같이 입력합니다.
$ git merge o2
10. 자동으로 빔이 실행되면서 'Merge branch o2'라는 커밋 메시지가 나타납니다. (자동으로 열리지 않을 수도 있습니다. 오류만 나타나지 않으면 병합은 잘 된 것입니다. 저도 안열렸습니다.) 브랜치를 병합하면서 만들어지는 커밋의 메시지 입니다. 커밋 메시지를 수정할 수도 있고, 자동 메시지를 그대로 사용해도 됩니다. esc 키를 누르고 :wq를 입력해 내용을 저장한 후 편집기를 종료합니다.
11. ls -al 명령을 사용해 확인해보면 o2 브랜치에 있던 o2.txt파일이 master브랜치에 합쳐졌을 것입니다.
12. git log --oneline --branches --graph 명령으로 브랜치와 커밋들이 어떻게 병합되었는지 확인할 수도 있습니다.
'o2 work 2' 커밋이 master 브랜치에 병합되면서 'Merge branch o2'라는 새로운 커밋이 생겼습니다. 두 브랜치에서 서로 다른 파일을 병합하는 경우 이렇게 간단히 깃에서 해결할 수 있습니다.
** 빨리감기 병합 **
master 브랜치에서 브랜치를 분기한 후에 master 브랜치에 아무 변화가 없다면(새로운 커밋을 만들지 않았다면) 분기한 브랜치를 병합하는 것은 간단합니다. 분기한 브랜치에서 만든 최신 커밋을 master브랜치가 가리키게만 하면 되기 때문입니다.
이 경우에는 화면에 커밋 해시가 업데이트 되었다는 내용과 함께 fast-forward라는 메시지가 나타납니다. 이런 병합을 빨리 감기 병합(fast-forward merge)이라고 부릅니다. git merge 명령의 결과가 단순히 포인터를 움직인 것이기 때문에 따로 커밋 메시지 창은 열리지 않습니다
--------------------------------------------------------------------------------------------------------------------
** 브랜치를 병합할 때 편집기 창이 열리지 않게 하려면 **
앞에서 브랜치를 병합할 때 자동으로 편집기가 실행되면서 커밋 메시지를 추가 작성할 수 있었습니다. (안그랬지만. 그렇다고 칩시다..) 만약 편집기 창을 열지 않고 깃에서 지정하는 커밋메시지를 그대로 사용하겠다면 다음과 같이 --no-edit 옵션을 추가합니다.
$ git merge o2 --no-edit
브랜치를 병합할 때 편집기 창이 나타나지 않도록 설정한 경우, 커밋메시지를 추가하거나 수정하고 싶다면 병합 명령에 --edit 옵션을 추가합니다.
$ git merge o2 --edit
-------------------------------------------------------------------------------------------------------------------------
<같은 문서의 다른 위치를 수정했을 때 병합하기>
master 브랜치와 o2브랜치에는 똑같이 work.txt 파일이 있습니다. 양쪽 브랜치에서 work.txt문서를 수정하되 서로 다른 위치를 수정한 후 브랜치를 병합했을 때 어떤 결과가 나오는지 확인해보겠습니다.
1. 홈 디렉터리로 이동한 후 manual-3라는 깃 저장소를 만들고 manual-3 디렉터리로 이동합니다
$ cd ~
$ git init manual-3
$ cd manual-3
2. 빔에서 work.txt 파일을 만들고 다음과 같이 입력합니다. 나중에 work.txt 문서를 수정하고 병합할 것이기 때문에 내용사이에 두줄의 공백을 두었습니다.
3. 방금 만든 work.txt를 스테이지에 올리고 커밋합니다. 커밋 메시지는 'work 1'이라고 하겠습니다
$ git add work.txt
$ git commit -m "work 1"
4. 'work 1'이라는 커밋을 만들었으므로 o2라는 새로운 브랜치를 만들어보겠습니다. 이제 master 브랜치와 o2 브랜치에는 모두 'work 1' 커밋이 있게 됩니다.
$ git branch o2
5. 양쪽 브랜치 모두에 있는 work.txt를 먼저 master 브랜치에서 수정하겠습니다.
$ vi work.txt
6. work.txt문서에는 '#title'와 '#content'가 2개씩 있습니다. 그중에서 첫번재 'content' 다음 줄에 'master content 2'라고 입력한 후 저장합니다.
7. 수정한 work.txt를 커밋합니다. 커밋메시지는 'master work 2'라고 하겠습니다
$ git commit -am "master work 2"
8. 이제 o2 브랜치의 work.txt 파일도 수정해 보겠습니다. 먼저 o2 브랜치로 체크아웃하고 work.txt 파일을 불러옵니다.
$ git checkout o2
$ vi work.txt
9. 이번에는 두번째 'content' 다음줄에 'o2 content 2'라고 입력하고 저장합니다.
10. 수정한 work.txt 파일을 커밋해보세요. 커밋 메시지는 'o2 work 2"라고 하겠습니다.
$ git commit -am "o2 work 2"
11. master 브랜치와 o2 브랜치 양쪽에서 work.txt 파일을 수정했지만 문서 안의 수정 위치는 다릅니다. 이런경우는 어떻게 해야 할까요? o2 브랜치를 master 브랜치에 합치기 위해 master 브랜치로 체크아웃 합니다.
$ git checkout master
12. git merge 명령을 사용해 o2 브랜치를 master 브랜치로 끌어옵니다.
$ git merge o2
13. 자동으로 빔이 실행되면서 커밋 메시지가 나타날 것입니다.(안나타날 수도 있습니다,) 메시지를 수정할 수도 있고 그대로 사용할 수도 있습니다.
14. 터미널 창에는 'Auto-merging work.txt'로 시작하는 병합완료 메시지가 나타납니다. o2 브랜치의 work.txt가 master 브랜치의 work.txt와 어떻게 병합되었을까요? cat 명령을 사용해 확인해봅시다.
$ cat work.txt
15. master 브랜치의 수정내용과 o2 브랜치의 수정 내용이 자연스럽게 하나의 파일에 합쳐진 것을 볼 수 있습니다. 이렇게 브랜치를 자동으로 합쳐주는 기능이 있엇 깃은 더욱 강력한 도구가 됩니다.
<같은 문서의 같은 위치를 수정했을 때 병합하기>
깃에서는 줄 단위로 변경여부를 확인합니다. 그래서 각 브랜치에 같은 파일 이름을 가지고 있으면서 같은 줄을 수정했을 때 브랜치를 병합하면 브랜치 충돌(conflict)이 발생합니다. master 브랜치와 o2 브랜치에서 같은 파일의 같은 위치를 수정한 후 병합해보면서 어떤 경우에 브랜치 충돌이 생기는지, 그리고 어떻게 충돌을 해결하는지 알아보겠습니다.
1. 홈 디렉터리로 이동한 후 manual-4라는 깃 저장소를 만들고 manual-4 디렉터리로 이동합니다.
$ cd ~
$ git init manual-4
$ cd manual-4
2.빔에서 work.txt 파일을 만들고 다음과 같이 입력합니다. 나중에 work.txt문서의 같은 위치를 수정하기 위해 두 내용 사이에 빈 줄을 하나만 두었습니다.
3. 방금 만든 work.txt를 스테이지에 올리고 커밋합니다. 커밋 메시지는 'work 1'이라고 하겠습니다.
$ git add work.txt
$ git commit -m "work 1"
4. 이제 o2라는 브랜치를 만듭니다. o2브랜치는 만들어지면서 master브랜치의 최근 커밋을 가져옵니다. 즉 브랜치 양쪽에 work.txt가 있습니다.
$ git branch o2
5. 아직 체크 아웃은 하지 않았으므로 현재 브랜치는 master입니다. 먼저 master 브랜치에서 work.txt를 수정하겠습니다.
$ vi work.txt
6. work.txt 문서에는 '#title'와 '#content'가 2개씩 있습니다. 그중에서 첫번째 'content' 다음 줄에 'master content 2'라고 입력한 후 저장합니다.
7. 수정한 work.txt를 커밋하세요. 커밋메시지는 'master work 2'라고 하겠습니다.
$ git commit -am "master work 2"
8. 이제 o2 브랜치의 work.txt 파일도 수정해보겠습니다. 먼저 o2 브랜치로 체크아웃합니다. 그리고 work.txt 파일을 엽니다.
$ git checkout o2
$ vi work.txt
9. master 브랜치에서 추가 내용을 입력했던 위치와 같은 곳에 'o2 content 2'라고 입력하고 저장합니다.
10. 수정한 work.txt 파일을 커밋해보세요. 커밋 메시지는 'o2 work 2'라고 하겠습니다.
$ git commit -am "o2 work 2"
11. master 브랜치와 o2 브랜치 양쪽에서 work.txt 파일을 수정했지만 문서 안의 수정위치가 같습니다. 이럴 경우 어떻게 병합될까요? o2 브랜치를 master브랜치에 병합하기 위해 먼저 master 브랜치로 체크아웃합니다.
$ git checkout master
12. git merge 명령을 사용해 o2 브랜치를 master 브랜치로 끌어옵니다.
$ git merge o2
13. 이전에 git merge 명령을 실행했을 때처럼 자동으로 빔이 열리지 않고 메시지가 나타납니다. (안열렸을수도 있어요..) 이 메시지는 work.txt를 자동 병합하는 동안 충돌(conflict)가 발생했다는 뜻입니다.
14. 충돌이 생긴 문서는 자동으로 병합될 수 없으므로 사용자가 직접 충돌 부분을 해결한 후 커밋해야합니다. 충돌이 생긴 work.txt는 어떻게 되어 있을지 빔으로 열어봅시다.
$ vi work.txt
15. work.txt의 내용이 조금 특별하게 되어있을 겁니다. master 브랜치에 있던 내용과 o2브랜치에 있던 내용이 한꺼번에 나타났기 때문입니다. '<<<<<<< HEAD'와 가운데 가로줄(========) 사이의 내용은 현재 브랜치, 즉 master 브랜치에서 수정한 내용입니다. 가로줄(=======)과 '>>>>>>> o2' 사이의 내용은 o2 브랜치에서 수정한 내용입니다. 양쪽 브랜치의 내용을 참고하면서 직접 내용을 수정해야 합니다.
16. 내용을 원하는대로 수정했으면 문서에 나타나 있던 '<<<<<HEAD'나 '>>>>>>>>o2', 가로줄(=======)은 삭제합니다.
다했으면 문서를 저장하고 종료합니다.
17. 이제 수정한 work.txt를 스테이지에 올리고 커밋하면 됩니다. 커밋 메시지는 'merge o2 branch'로 하겠습니다. 이렇게 해서 o2 브랜치에서 병합한 work.txt의 충돌을 해결하고 커밋했습니다.
18. git log 명령에 --oneline과 --branches, --graph 옵션을 사용하면 지금까지 만든 브랜치와 커밋의 관계를 한눈에 확인할 수 있습니다.
**병합 및 충돌 해결 프로그램**
프로젝트 규모가 클수록 브랜치가 많으므로 브랜치에서 병합해야 할 파일도 많아집니다, 그만큼 충돌이 많이 생기기 때문에 깃의 브랜치 병합을 자동으로 처리해주고 충돌을 해결해주는 프로그램이 많습니다. 3 way merge를 지원하는 프로그램을 선택하는 것이 좋습니다. 다음은 자주 사용하는 병합 자동화 프로그램입니다.
P4Merge //무료이고 직관적이며 사용이 편리하고 병합 기능이 뛰어납니다. 단축키가 지원되지 않는 단점이 있습니다.
Meld // 무료이며 오픈소스입니다. 파일을 비교하는 것 뿐만 아니라 직접 편집할 수 있습니다.
Kdiff3 // 무료이고 사용이 편리하고 병합기능이 뛰어나지만 한글이 깨져보일수도 있습니다.
Araxis Merge // 유료지만 용량이 큰 파일에서도 잘 작동합니다.
-------------------------------------------------------------------------------------
<병합이 끝난 브랜치 삭제하기>
브랜치를 병합한 후 더이상 삭제하지 않는 브랜치는 깃에서 삭제할 수 있습니다. 단 이렇게 브랜치를 삭제하더라도 이 브랜치가 완전히 지워지는 것이 아니라 다시 같은 이름의 브랜치를 만들면 예전 내용을 다시 볼 수 있습니다.
1. git branch 명령을 사용하면 현재 저장소에 어떤 브랜치가 있는지 확인할 수 있습니다. 앞의 브랜치 병합 실습을 따라왔다면 현재 master 브랜치와 o2 브랜치가 있을 겁니다.
$ git branch
2. 저장소의 기본 브랜치는 master 이므로 브랜치를 삭제하려면 master브랜치에서 해야합니다. 현재 브랜치가 master 브랜치가 아니라면 master 브랜치로 체크아웃하세요
$ git checkout master
3. 브랜치를 삭제할 때는 git branch 명령에 -d 옵션을 사용합니다. 다음과 같이 o2 브랜치를 삭제합니다.
$ git branch -d o2
** master 브랜치에 병합하지 않은 브랜치를 삭제하려면 오류메시지가 나타납니다. 이럴 경우 옵션 -d 대신 -D(대문자)를 사용하여 강제로 브랜치를 삭제할 수 있습니다. ***
4. 'Deleted branch o2'처럼 메시지가 나타나면 성공적으로 브랜치가 삭제된 것입니다. 삭제한 브랜치는 같은 이름으로 다시 브랜치를 만들면 예전에 작업했던 내용이 그대로 나타납니다. 즉, 브랜치를 삭제한다는 것은 완전히 저장소에서 없애는 것이 아니라 깃의 흐름속에서 감추는 것이라고 생각하면 됩니다.
728x90'Git&GitHub > Git Branch' 카테고리의 다른 글
[Git Branch] (7) 브랜치 관리하기 (0) 2022.05.18 [Git Branch] (5) 브랜치 사이의 차이점 알아보기 (0) 2022.05.18 [Git Branch] (4) Git Branch 정보 확인하기 (0) 2022.05.18 [Git Branch] (3) Git Branch 브랜치 사이 이동하기 - git checkout (0) 2022.05.18 [Git Branch] (2) Git Branch 만들기 (0) 2022.05.18