본문
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 파일이 있다고 가정할게요.
- base : 두 브랜치의 공통 부모 커밋의 sample.txt 파일의 내용 중 일부 = 위 그림 (1)번
- master : 마스터 브랜치의 최신 커밋의 sample.txt 파일의 내용 중 일부 = 위 그림 (2)번
- premium : 프리미엄 브랜치의 sample.txt 파일의 내용 중 일부 = 위 그림 (3)번
- 머지 결과 : 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 머지
이렇게 두 가지 종류가 있다는 사실만큼은 꼭 기억하세요.
댓글