브랜치와 수술

머지 옵션

평범한 머지는 버튼 하나면 끝이고, 대부분의 경우 그게 이야기의 전부예요. 이 페이지는 나머지 경우를 위한 것이에요. 머지할 때마다 부딪히는 잠금 파일, 누군가 들여쓰기를 다시 한 파일, 경로가 서로 맞지 않는 벤더링된 프로젝트. git은 이 세 가지를 위한 스위치를 오래전부터 갖고 있었어요. 다만 충돌이 난 와중에는 아무도 열어 보지 않는 매뉴얼 페이지에 묻혀 있을 뿐이에요.

브랜치를 우클릭 → 옵션을 지정해 머지… — 사이드바의 브랜치 행과 원격 행에서, 그리고 하나의 메뉴 블록을 공유하는 그래프의 색깔 있는 ref 배지에서 — 또는 ⌘K → 옵션을 지정해 머지.

머지 옵션과 그 아래에 그대로 적힌 git 명령

명령은 옵션을 조립하는 대로 화면에 찍혀요. 매뉴얼과 대조해 보라고, 그리고 다음 번에는 이 대화 상자 없이 터미널에서 실행하라고 거기 있는 것이에요.

헝크가 충돌할 때

선택 플래그 의미
멈추고 물어보기 — 기본값. 직접 해결해요
이 브랜치 쪽을 유지 -X ours 부딪히는 헝크는 이미 체크아웃되어 있는 쪽으로 해결돼요
들어오는 쪽을 채택 -X theirs 부딪히는 헝크는 들어오는 브랜치 쪽으로 해결돼요

-X ours는 -s ours가 아니에요. 여기의 스위치는 실제로 부딪히는 헝크만 결정해요. 다른 브랜치의 나머지 변경은 모두 정상적으로 머지돼요. ours라는 이름의 전략은 — Gitcito는 제공하지 않아요 — 여러분의 트리를 통째로 가져가고 반대쪽은 버려서, 담고 있지도 않은 작업을 담았다고 주장하는 머지 커밋을 만들어요. 그 구분이 git 머지에 대해 가장 많이 오해받는 단 하나의 지점이에요.

모든 것을 결정해 주지는 못해요. 수정/삭제 충돌 — 한쪽은 파일을 편집하고 다른 쪽은 삭제한 경우 — 은 내용 헝크가 아니라서 -X는 그것을 여러분 몫으로 남겨 둬요. 그게 맞아요. 삭제된 파일이 돌아와야 하는지에 대해 "우리 쪽을 선호한다"가 답이 되는 경우는 없으니까요.

공백

선택 플래그
기존 공백의 변경을 무시 -X ignore-space-change
공백을 전부 무시 -X ignore-space-at-eol, -X ignore-all-space

이것이 존재하는 이유가 되는 사례: 한 브랜치가 파일의 들여쓰기를 다시 했고(또는 포매터가 했고), 다른 쪽은 같은 줄을 편집했어요. git은 한 줄에 두 개의 편집이 있다고 보고 멈춰요. 공백을 무시하면 들여쓰기 재조정은 저울에 올릴 변경이 아니게 되고, 진짜 편집이 그대로 머지돼요.

결과는 반대쪽이 건드린 줄에 대해 그쪽의 공백을 유지하므로, 이어서 포매터를 한 번 돌리는 것도 나쁘지 않은 생각이에요.

무엇을 기록할 것인가

선택 플래그 남는 것
가능하면 fast-forward — 히스토리가 갈라졌을 때만 머지 커밋
항상 머지 커밋 만들기 --no-ff fast-forward가 가능해도 머지 커밋을 만들어, 그래프에 브랜치가 영원히 보이게
fast-forward만, 아니면 거부 --ff-only 진짜 머지가 필요했다면 아무것도 남지 않아요. 검사용으로 유용
스쿼시 --squash 변경은 스테이징되고, 머지는 기록되지 않으며, 커밋은 직접 써요
머지하되 커밋은 하지 않기 --no-commit 머지가 스테이징된 채 진행 중이라, 먼저 살펴보거나 고칠 수 있어요

스쿼시와 --no-commit은 같지 않아요. 스쿼시는 머지가 있었다는 사실 자체를 잊어요. git은 두 번째 부모를 기록하지 않고, 다음번에 그 브랜치는 머지되지 않은 것으로 보여요. --no-commit은 그저 여러분을 기다리고 있는 진행 중인 머지예요. MERGE_HEAD가 설정되어 있고, 커밋하면 평소대로 마무리돼요.

--ff-only는 조용히 실패하지 않아요. 머지 커밋이 필요하다면 git은 거부하고 아무것도 움직이지 않아요. 스크립트로 돌리는 머지 전에 좋은 안전 점검이 되는 이유가 바로 그것이에요.

전략

전략 용도
기본 (ort) 모든 경우. git의 현대적인 3-way 머지
subtree 양쪽이 서로 다른 경로에 있을 때 — 이 프로젝트의 하위 디렉터리로 벤더링된 프로젝트
resolve 옛 3-way 머지. 교차 히스토리에서 ort가 포기하는 경우 가끔 성공해요

기억해 둘 만한 것은 -s subtree예요. vendor/parser/에 들어 있는 프로젝트의 업데이트를 머지하면 그러지 않고서는 "모든 파일 삭제, 모든 파일 추가"로 읽히게 돼요. subtree 전략은 경로가 얼마나 밀렸는지를 먼저 계산해요. 전체 워크플로는 서브트리를 보세요.

왜 충돌하는가

충돌 해결기 안에는 왜 충돌하는가 버튼이 있어요. 눈앞의 파일에 대해 git log --merge를 실행해서, 브랜치가 갈라진 뒤로 그 파일을 건드린 커밋을 양쪽별로 나열해요.

충돌한 파일을 건드린 양쪽의 커밋들

충돌 마커는 무엇이 부딪히는지를 말해 줘요. 이것은 누가, 언제, 왜 바꿨는지를 말해 줘요. 보통은 그쪽이 해결 방식을 실제로 결정하는 질문이고, 한쪽을 고르기 전에 누군가에게 물어보러 가야 할 이유예요.

아무것도 나오지 않는다면 어느 쪽도 정확히 이 파일에 대한 변경을 커밋하지 않은 것이에요. 부딪힘은 더 윗단의 이름 변경이나 디렉터리 이동에서 와요.

알아 둘 만한 한계

  • 옵션은 한 번의 머지에만 적용돼요. 기억되지 않으며, 평범한 현재 브랜치로 머지 항목이나 드래그 앤 드롭 메뉴를 바꾸지도 않아요.
  • 되돌리기는 여전히 동작해요: 옵션을 지정해 실행한 머지도 같은 되돌리기 항목을 기록하며, ORIG_HEAD로 리셋해요.
  • 옥토퍼스 머지(한 번에 두 개를 넘는 브랜치)는 여기서 제공하지 않아요.
  • 커밋 메뉴의 ref별 "X를 Y로 머지" 항목은 평범한 머지로 남아요. 옵션을 원한다면 ref 배지 자체를 쓰세요.
  • -X는 조용히 결정해요. 어떤 헝크가 자동으로 해결되었는지 아무 표시도 남지 않으므로, 중요한 머지에서는 충돌이 없다는 사실을 믿기보다 나중에 차이를 읽어 보세요.

함께 보기: 머지와 리베이스 · 충돌 · 서브트리 · 충돌 레이더

GitHub에서 이 번역 개선하기