본문

14. 새로운 커밋을 만들지 않는 merge도 있습니다(심화)

반응형

머지(merge)에 관한 좀더 깊은 이야기를 해볼게요. 머지를 하면 새로운 커밋이 생긴다고 했습니다.

그리고 머지를 통해서 생겨난 커밋을 머지 커밋(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 브랜치를 머지했을 때 다양한 상황별로 그 결과가 정리되어 있는데요.

경우basemasterpremium머지 결과

case1 A A B -> B
case2 1 2 1 -> 2
case3 "hello" (공백) "hello" -> (공백)
case4 "bye" "fighting" "please" -> Conflict 발생!

각 컬럼(column, 열)에 대해서 설명할게요. 지금 모든 커밋에 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 때와는 다른 변화가 일어났는데요. 이렇게 두 브랜치에서 다 변화가 있을 때 Git은 어떤 변화를 선택해야할까요? 정답은 바로 'Git도 모른다!' 입니다. 사실, 바로 이런 경우에 여러분이 배운 Conflict가 발생합니다. 이전에 Conflict가 발생했을 때 그것을 해결하고 머지를 마무리했던 거 기억나시죠? 바로 이런 경우였던 겁니다.

3-way merge가 어떤 방식으로 이루어지는지 아시겠죠?

  • base때의 내용과 비교했을 때 달라진 부분이 있는 것이 우선시되고,
  • 두 브랜치에서 둘다 변화가 일어났을 때는 Conflict를 발생시켜서 사용자가 스스로 선택하게끔 한다는 걸 기억하시면 됩니다.

자, 이때까지 머지에 대해서 좀 깊게 배워봤습니다. 방금 배운 내용을 다 기억하지 못하더라도

머지의 종류에는 크게

  • Fast-forward 머지
  • 3-way 머지 

이렇게 두 가지 종류가 있다는 사실만큼은 꼭 기억하세요.

반응형

공유

댓글