Git 재활 훈련 2일차 - Merge

0

Git

목록 보기
2/14

Merging Branch - fast-forward

나뉘어진 branch들은 서로 merge할 수 있고, 이것이 branch를 나눈 가장 큰 이유이다.

branch 간의 merge는 commit간의 merge가 아니다. 즉, branch 끼리의 merge이고, 항상 branch의 HEAD와 병합하는 것이다.

  • fast-forward merge
                [Master] <- HEAD
                    |
                    |
(987fac...)  --> (236ff...) --> (92faa...) --> (2456...)
                                                    |
                                                    |
                                                  [Bugfix] <- HEAD

다음의 경우 Master branch를 Bugfix branch와 merge하는 것이다. 그런데, 잘보면 이들은 분기되어 있지 않고, 하나의 라인이 쭉 이어진 모습이다. 따라서 Master branch가 Bugfix branch를 따라 잡는 것이 전부이다. 따라서 'fast-forward' merge라고 하는 것이다.

git merge bugfix

이렇게 merge하면 다음과 같이 된다.

                                            [Master] <- HEAD
                                                    |
                                                    |
(987fac...)  --> (236ff...) --> (92faa...) --> (2456...)
                                                    |
                                                    |
                                                  [Bugfix] <- HEAD

이를 실제로 사용해보기 위해서 master branch에서 다음과 같이 실행해보도록 하자.

echo "playlist" >> ./playlist.txt

git add .
git commit -m "add: playlist.txt"

다음으로 bugfix branch를 만들고, playlist.txt에 다른 문장을 추가로 넣도록 하자.

echo "goodbye world" >> ./playlist.txt

git add .
git commit -m "update playlist.txt"

git log를 통해서 확인해보도록 하자.

git log
commit b0ca514a88a87c85100c3e4fa6f78fd0d2131f27 (HEAD -> bugfix)
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:03:03 2024 +0900

    update playlist.txt

commit 5e0b744603ffe57d69bf755d92fbde76191d150a (master)
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:01:23 2024 +0900

    add: playlist.txt

master의 HEAD와 bugfix의 HEAD가 다르다는 것을 볼 수 있다. 이제 master에서 bugfix의 변동 사항을 반영해보도록 하자.

git switch master
git merge bugfix
Updating 5e0b744..b0ca514
Fast-forward
 playlist.txt | 1 +
 1 file changed, 1 insertion(+)

Fast-forward가 나오는 것을 볼 수 있다. git log를 통해서 확인해보도록 하자.

git log

commit b0ca514a88a87c85100c3e4fa6f78fd0d2131f27 (HEAD -> master, bugfix)
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:03:03 2024 +0900

    update playlist.txt

commit 5e0b744603ffe57d69bf755d92fbde76191d150a
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:01:23 2024 +0900

    add: playlist.txt

성공적으로 merge된 것을 볼 수 있다. 이렇게 성공적으로 merge된 이유는 fast-forward 자체가 굉장히 쉬운 merge이기 때문이다. 즉, 기존 code에 대한 conflict가 없기 때문이다.

Merging Branch

세상 모든 merge가 fast-forward처럼 단순하지 않다. 이번에는 다음과 같은 경우를 생각해보도록 하자.

                               [Master] <- HEAD
(987fac...)  --> (236ff...) --> (92faa...)
                     |
                     |
                 (92faa...) --> (2456...)
                               [Bugfix] <- HEAD

다음과 같이 236ff... commit 이후로 master branch와 bugfix branch가 분기되었다고 하자. 어떻게 이들을 merge시킬 수 있을까??

사실 이 경우 두 branch가 분기되어 충돌이 발생했거나, 안했거나를 생각할 수 있다. 먼저 충돌이 발생하지 않은 경우를 생각해보도록 하자.

이 경우 새로운 commit을 생성하는데, 이를 병합 commit이라고 한다.

                                             [Master] <- HEAD
(987fac...)  --> (236ff...) --> (92faa...) --> (NEW COMMIT)
                     |
                     |
                 (92faa...) --> (2456...)
                               [Bugfix] <- HEAD

다음과 같이 새로운 commit을 만드는데 이를 병합 commit이라고 한다. 이 병합 commit을 분기된 branch인 bugfix와 연결하면 된다.

                                             [Master] <- HEAD
(987fac...)  --> (236ff...) --> (92faa...) --> (NEW COMMIT)
                     |                                |
                     |                                |
                 (92faa...) --> (2456...)--------------
                               [Bugfix] <- HEAD

이렇게 merge하면 성공이다.

test하기 위해서 test.txt를 만들자.

touch ./test.txt

다음으로 out branch를 만들고 test.txt를 수정해보도록 하자.

git switch -c out
echo "test opt" >> ./test.txt 

git add ./test.txt
git commit -m "update test.txt"

master branch로 돌아가서, playlist.txt를 수정해보도록 하자.

git switch master
echo "playlist3" >> ./playlist.txt

git add .
it commit -m "update playlist.txt"

이제 master branch와 out branch를 merge하도록 하자.

git merge out
...
Merge branch 'out'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit

위와 같이 merge commit에 대한 message를 쓰라고 나올 것이다. merge해주면 다음과 같은 결과가 나온다.

Merge made by the 'recursive' strategy.
 test.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

이제 git log를 확인해보면 다음과 같다.

(HEAD -> master)
Merge: 2d27a7c ca17051
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:33:40 2024 +0900

    Merge branch 'out'

commit 2d27a7c1fbf6ea03626a6f1d676cee4feaf0ccaf
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:32:43 2024 +0900

    update playlist.txt

commit ca17051e828837dd6b89e66e8390754be48a9090 (out)
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:29:24 2024 +0900

    update test.txt

merge에 성공한 것이다. 이제 merge 도중에 충돌이 발생한 경우를 확인해보도록 하자.

Merging Branch - conflict

conflict가 발생하는 경우는 대부분 하나의 file을 여러 branch가 수정하는 경우에 발생한다. 이 경우 직접 merge conflict를 해결해야한다.

conflict가 발생한 부분을 보면 다음과 같이 표시될 것이다.

<<<<<<< HEAD
I have 2 cats
I also have chickens
=======
I used to have a dog 
>>>>>>> bug-fix

HEAD부분이 현재 branch에 대한 내용이고, =======아래에서 bug-fix까지가 merge하려는 branch의 부분이다. 이 둘 중에 어느 것을 쓸 것이며, 어떻게 합칠 것인지 스스로 결정하면 된다.

먼저 새로운 branch인 conflict를 만들고, playlist.txt를 다음과 같이 수정하도록 하자.

git switch -c conflict
echo "playlist conflict" >> ./playlist.txt
git add ./playlist.txt
git commit -m "Overwrire playlist.txt"

다음으로 master branch로 돌아와서 playlist.txt를 다음과 같이 수정해주도록 하자.

git switch master
echo "master playlist" > ./playlist.txt
git add ./playlist.txt
git commit -m "Overwrite playlist.txt"

이제 이 둘을 master branch에서 conflict branch의 내용을 merge하도록 하자.

git merge conflict 

Auto-merging playlist.txt
CONFLICT (content): Merge conflict in playlist.txt
Automatic merge failed; fix conflicts and then commit the result.

playlist.txtCONFLICT가 발생했다는 것을 알 수 있다.

  • palylist.txt
<<<<<<< HEAD
master playlist
=======
playlist
goodbye world
playlist3
playlist conflict
>>>>>>> conflict

다음과 같이 HEADconflict가 있다. HEAD가 우리의 원본 내용이고, =======에서 >>>>>>>까지가 merge하려는 branch의 내용인 것이다. 이 중에 어느 것을 어떻게 선택하고 사용할 것인지는 오로지 개발자의 몫에 달렸다. 일부만 반영할 수도 있고, 둘 다 반영할 수 있도 있다. 우리의 경우는 모두 반영하도록 하자.

  • palylist.txt
master playlist
playlist
goodbye world
playlist3
playlist conflict

이 다음 merge commit을 만들어줘야 한다. 즉 working directory에 있는 merge된 playlist를 repository로 반영해야한다는 것이다.

git add ./playlist.txt
git commit -m "merge master and conflict"
[master b0c183c] merge master and conflict

git log를 통해서 확인해보도록 하자.

git log
commit b0c183c7d04941777ff0a844d8c5d998018388fb (HEAD -> master)
Merge: 6ccaa88 028445e
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:52:13 2024 +0900

    merge master and conflict

commit 6ccaa884193b3ffbc4028e895f77441150a08248
Author: calo <calo@calo.com>
Date:   Wed Jul 31 19:47:40 2024 +0900

    Overwrite playlist.txt

정리하자면 다음과 같다.

  1. 병합하려는 branch를 선택하여 git merge
  2. merge conflict 발생 시에 file에 직접 가서 수정
  3. git commit을 통한 merge commit 생성

0개의 댓글