상세 컨텐츠

본문 제목

Git에서 branch merge 방법들과 각 방법의 특징

성장일지

by 모모87 2024. 6. 7. 05:45

본문

Git merge란?

 

git branch를 다른 branch로 합치는 과정을 merge라 한다.

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

 

git merge <병합할 브랜치명>

 

 

 

병합하는 브랜치 사이의 관계에 따른 merge 종류

 

  1. Fast-forward 머지
  2. 3-way 머지

 

머지를 하면 새로운 커밋이 생긴다.

그리고 머지를 통해서 생겨난 커밋을 머지 커밋(merge commit)이라고 부른다.

이 그림을 보면 지금 master 브랜치에서 premium 브랜치를 머지해서 검은색의 머지 커밋이 생긴 것을 알 수 있다.

하지만 머지를 한다고 항상 이렇게 새로운 커밋이 생기는 건 아니다.

 

지금 저는 master 브랜치에 HEAD가 master 브랜치를 가리키고 있다.

이 상태에서 git merge premium 을 실행하면 어떻게 될까?

 

premium 브랜치가 가리키던 커밋을, master 커밋도 똑같이 가리키게 된다. 지금 총 커밋 수는 그대이다.

이렇게 새로운 커밋이 생기는 게 아니라 단지 브랜치가 이동하게 되는 머지를 Fast-forward 머지라고 한다.

Fast-forward는 어떤 영상이나 소리를 빨리감기(앞으로 감기)한다는 뜻이다.

지금 master 브랜치가 더 최신 커밋으로 이동하는 모습이 꼭 빨리감기같다.

 

커밋 히스토리에서 같은 선(line) 상에 있는 브랜치를 머지할 때 Fast-forward 머지가 이루어진다.

방금 전에는 master 브랜치와 premium 브랜치가 둘다 같은 선 상에 있는 바로 이런 경우이다.

 

이 그림처럼 두 브랜치가, 커밋 히스토리 상에서 분리된 2개의 선에 각각 존재할 때 머지를 하면 머지 커밋이 새롭게 생긴다.

그리고 이런 머지는 3-way merge라고 한다.

이름이 3-way인 이유는 지금 1, 2, 3 표시한 3가지 커밋을 고려해서 머지를 하기 때문이다. 

  • (1)번 : 두 갈래로 갈라지기 전 공통 조상이 되는커밋
  • (2)번 : 한 브랜치가 가리키는 커밋
  • (3)번 : 다른 브랜치가 가리키는 커밋

3-way merge는 자신만의 방식을 갖고 이 3가지 커밋을 기준으로 머지 커밋을 자동으로 만들어낸다.

아래 표에는 master 브랜치와 premium 브랜치를 머지했을 때 다양한 상황별로 그 결과가 정리되어 있다.

경우 base master premium
머지 결과
case1 A A B -> B
case2 1 2 1 -> 2
case3 "hello" (공백) "hello" -> (공백)
case4 "bye" "fighting" "please" -> Conflict 발생!

 

(모든 커밋에 sample.txt 파일이 있다고 가정)

  1. base : 두 브랜치의 공통 부모 커밋의 sample.txt 파일의 내용 중 일부 = 위 그림 (1)번
  2. master : 마스터 브랜치의 최신 커밋의 sample.txt 파일의 내용 중 일부 = 위 그림 (2)번
  3. premium : 프리미엄 브랜치의 sample.txt 파일의 내용 중 일부 = 위 그림 (3)번
  4. 머지 결과 : master 브랜치에서 premium 브랜치를 머지했을 때의 최종 결과

 

case1

지금 base가 A이고, master는 A, premium은 B

그럼 base를 기준으로 볼 때, master에서는 변화가 없었지만, premium에서는 A가 B로 변경된 상태.

3-way merge는 base에서 변화가 발생한 것을 우선 채택 . 그래서 머지 결과는 'B'.

 

case2

지금 base가 1, master는 2, premium은 1

이 경우에도 base에서 변화가 발생한 2가 머지 결과가 됨.

 

case3

지금 base가 "hello"이고, master는 "hello"를 삭제한 공백 상태, premium은 "hello"

"hello"를 삭제해서 공백 상태가 된 것이 변화가 더 발생한 것이기 때문에 머지 결과는 공백.

 

case4

지금 base가 "bye", master가 "fighting", premium이 "please"

둘 다 base 때와는 다른 변화가 생김.

사실, 바로 이런 경우에   Conflict가 발생

 

충돌을 해결하는 방법은 ‘<<<<<<< 현재 브랜치명’ , ‘=======’, ‘>>>>>>> 병합할 브랜치명’ 을 지우고 원하는 변경 방향을 정하여 설정한 뒤 저장하고, git add 로 충돌이 발생한 파일을 stage 위에 올리고, commit 하면 Fig5 와 같이 병합이 완료된 상태로 만들 수 있다.

그러나 충돌이 발생한 상태에서 커밋하기 전에, 병합을 취소하고 싶으면 ‘git merge --abort’ 명령어를 사용하여 취소할 있다.

 

  

반응형

관련글 더보기