Dev-Tino

Dev-Tino 4주차:: Git 3 way merge

2학년이 될 때까지는 github을 만들어 포트폴리오를 쌓으라는 말만 들었지, co-op한 적이 없어 github을 쓴 적이 없었는데. 3학년으로 올라오니 github을 이용하여 과제 할 일이 정말 많았다. merge와 rebase를 급하게 배우고 적용했다. conflict 오류도 자주 냈다. 다른 것도 있지만 어떤 부분을 작업할지 (역할 분담)를 제대로 나누지 않고 무작정 rebase와 merge 버튼만 눌러서였다.

이 글에서는 git으로 행할 수 있는 세 가지 merge 방식(3-way merge)을 설명한다. 다른 형상 관리 툴과는 달리 git은 branch(분기)를 생성할 때 파일을 복사하지 않고 파일의 스냅샷만을 가지고 생성하기 때문에, 자원의 부담 없이 branch를 만들어 사용할 수 있다. 이 장점때문에 git으로 작업을 할 때에는 다양한 용도의 branch를 만들어 사용한다.

Merge&Rebase

branch를 만들면 다시 한 번 branch를 합쳐야 한다. 이 때 쓰는 것이 Merge와 Rebase이다. 다른 사람과 할 때 git을 이용하여 형상 관리를 해야 한다면, branch간 병합에 사용하는 merge와 rebase의 차이점을 잘 알아두는 것이 좋다.

Merge

Merge, 한국 말로 ‘병합한다’를 이르는 이 말을 git에서는 ‘어느 한 브랜치와 다른 브랜치를 합칠 때’ 사용한다.

merge의 기본 단위는 브랜치이며, git merge 명령어로는 commit 단위 합치기가 불가능하다.

이 Merge에는 세 가지 방식이 있다. Fast Forward Merge, 3-way merge, squash가 바로 그것이다.

Fast Foward Mege 방식은 가장 기본적인 병합 방식이다. 이는 기존 브랜치와 분리된(분기한) 브랜치의 관계 기준으로, 분기한 브랜치의 커밋 히스토리가 기존 브랜치의 커밋 히스토리를 포함하고 있다면- (위 사진의 브랜치 B를 예시로 들 수 있다. B는 브랜치 A의 커밋 히스토리인 A->B를 포함하고 있다.) 이 관계는 Fast-Forward이다. 이 Fase Forward 관계일 때에는 별다른 옵션을 주지 않고 병합할 시 Merge Commit은 발생하지 않고 Head의 위치만 바뀐다.

이 때에는 'git merge {병합할 브랜치명}‘ 명령어를 사용한다.

병합하게 될 시 브랜치를 따라 가게 된다.

3 way merge

그러나 위와 같은 Fast Forward가 아닐 때도 존재한다.

위 사진을 보면, master 브랜치의 최상단 브랜치 C는 A>B>C commit을 거쳤고 feature branch는 A>B>X>Y 브랜치를 거쳤다. Fast Forward와 달리 Feature 브랜치가 master 브랜치의 모든 commit 정보를 가지고 있지 않다.

이 때 master 브랜치와 Feature 브랜치를 병합하게 되면 단순한 커밋 이동이 일어나지 않고, 새로운 commit이 생기며 병합하게 된다. 이것이 3-way merge라 불리는 이유는 내용을 병합할 때, base와 각 브랜치 2개가 참조하는 commit을 기준으로 병합을 진행하기 때문이다.

이 때에는 base와 각 branch가 참조하는 commit을 고려하여 자동 병합을 진행하는데, 이 때 두 commit이 동일한 곳을 변경할 경우 충돌(conflict)이 발생할 수 있다. 이 경우 conflict를 해결해야 함을 유념한다.

Squash

위와 비슷하면서도 다른 예시로 Squash가 있다. Squash는 여러개의 commit을 하나의 commit으로 합치기 위한 방법이다. 병합할 브랜치의 모든 커밋을 하나의 커밋으로 Squash한 (누른) 뒤 새로운 commit을 브랜치에 추가하는 식으로 병합하는 방식이다.

이 때, Squash를 행할 시 모든 commit 이력이 하나의 commit으로 합쳐지며 사라진다는 점을 유의하여야 한다.

$ git checkout main

$ git merge --squash my-branch

$ git commit -m "squash & merge"

이 때 사용하는 명령어이다.

Rebase

base를 재설정한다는 뜻. 하나의 브랜치가 다른 브랜치에서 파생되어 나온 경우, 다른 브랜치에서 진행된 커밋을 다시 가져와 base를 재설정하는 것이다. 새로운 commit을 기반으로 작업함으로써 파생된 브랜치는 병합 시에 conflict 없이 자신의 브랜치에 진행된 commit을 반영할 수 있다.

Rebase를 알기 전에는 Base에 대해 알아야 한다. Base는 특정 가지의 뿌리, 이전 가지이다.

위 사진의 my branch는 main 브랜치의 A commit에서 분기되었는데. 이 때 my branch의 Base는 A 커밋이다. 이 my branch의 Base를 재설정하는 것. 그게 바로 Rebase 방식이다. 위 그림의 경우 F, G, H의 Base가 C commit으로 옮겨졌음을 알 수 있다.

Squash가 아예 분기를 없앤다면 ReBase는 Base를 옮기는 느낌이라는 것을 염두에 두고, 상황에 맞는 방식을 사용하는 것이 좋다.

다른 명령어에 대해서는 이 게시글을 참고하자::

[참고 자료]

-https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html

-https://wikidocs.net/153693

-https://abled.tistory.com/15

-https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%99%80-Merge-%EC%9D%98-%EA%B8%B0%EC%B4%88 //공식 사이트

-https://kotlinworld.com/277

-https://velog.io/@devp1023/GIT-%EB%B3%91%ED%95%A9-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0-3-way-merge-fast-forward

-https://otzslayer.github.io/git/2021/12/05/git-merge-fast-forward.html

-https://cross-the-line.tistory.com/20

카테고리
#기타

댓글 0



추천 포스트