LabHub
배우기 러닝패스 코스

Git 실전 · 같은 충돌을 네 번째 풀고 있다 · 이론

같은 충돌을 세 번째 푸는 사람은 무언가를 놓치고 있다

LabHub 에서 이어서 보기

한 줄 요약

rerere 는 충돌을 어떻게 풀었는지 기록해 두었다가 **같은 충돌이 다시 나오면 그대로
적용**합니다. merge.conflictStyle=zdiff3 는 충돌 표시에 공통 조상을 함께 보여 줘서
"누가 무엇을 바꿨는지" 를 추측하지 않게 합니다. -X ours-s ours 는 이름만
비슷하고 결과가 전혀 다릅니다.

왜 이게 필요했나

오래 사는 기능 브랜치를 main 위로 계속 리베이스하면, 같은 자리에서 같은 충돌이
매번 납니다. 열 개 커밋을 리베이스하면 그 충돌을 열 번 풉니다. 실수로 --abort 하고
다시 하면 또 열 번입니다. 지치면 손이 미끄러지고, 미끄러진 해결은 조용히 커밋됩니다.

그리고 충돌 표시 자체가 정보가 부족합니다. 기본 표시는 이렇게 나옵니다.

<<<<<<< HEADb by main=======b by topic>>>>>>> topic

여기서 알 수 없는 것이 하나 있습니다 — 원래 무엇이었나. 한쪽이 지운 것인지, 양쪽이
서로 다르게 고친 것인지, 한쪽은 그대로 두고 다른 쪽만 고친 것인지가 구별되지 않습니다.
그래서 "안전해 보이는 쪽" 을 고르게 되고, 그 판단이 틀리면 남의 수정이 사라집니다.

어떻게 동작하나

zdiff3 — 공통 조상을 함께 보여 준다

git config merge.conflictStyle zdiff3

그러면 충돌 표시에 가운데 칸이 하나 더 생깁니다.

<<<<<<< HEADb by main||||||| 75364cdb=======b by topic>>>>>>> topic

||||||| 아래가 공통 조상의 내용입니다. 이제 "원래 b 였는데 양쪽이 서로 다르게
고쳤다" 가 한눈에 보입니다. diff3 이라는 옛 설정값도 같은 일을 하는데, zdiff3
(git 2.35 이상)는 양쪽에 공통으로 남은 줄을 충돌 바깥으로 빼 줘서 표시가 짧습니다.

rerere — 해결을 기억한다

git config rerere.enabled true

켜 두면 충돌이 났을 때 git 이 충돌 전 모습(preimage).git/rr-cache
기록하고, 커밋할 때 해결한 결과(postimage) 를 같은 자리에 붙여 둡니다. 다음에
똑같은 preimage 가 나오면 이렇게 말합니다.

Resolved 'handler.txt' using previous resolution.

주의할 것이 셋 있습니다. 첫째, rerere 는 해결을 적용만 하고 스테이징하지는 않습니다.
결과를 보고 git add 하는 것은 사람의 몫입니다(rerere.autoUpdate 를 켜면 자동으로
스테이징되지만, 그러면 확인 없이 지나가게 되므로 권하지 않습니다). 둘째, 기록은
.git 안에 있어서 내 기계에만 남습니다. 셋째, 잘못 푼 해결도 똑같이 기억합니다 —
그때는 git rerere forget <경로> 로 그 기록을 지워야 합니다.

-X ours-s ours 는 전혀 다르다

이름이 비슷해서 자주 헷갈립니다.

| 손잡이 | 무엇인가 | 결과 |
| --- | --- | --- |
| -X ours | 기본 병합 전략에 주는 옵션 | 충돌한 자리만 우리 것으로 고르고, 충돌하지 않은 상대 변경은 그대로 들어온다 |
| -s ours | 전략 자체 | 상대 트리를 통째로 버린다. 결과 트리는 병합 전 우리 것과 한 글자도 다르지 않다 |

-s ours 는 "이 브랜치는 합치지 않기로 했다" 는 사실을 이력에 남기는 용도입니다.
상대 브랜치가 조상으로 붙으므로 다음부터 그 브랜치는 병합 대상에서 빠집니다. 내용을
가져오려는 의도로 이것을 쓰면, 이력에는 합쳐졌다고 적혀 있는데 코드에는 아무것도
들어오지 않은 상태가 됩니다 — 그리고 나중에 누구도 그것을 의심하지 않습니다.

현장에서 만나는 모습

다음 실습에서 할 것

같은 자리를 서로 다르게 고친 두 브랜치를 만들어, 기본 표시와 zdiff3 표시를 나란히
봅니다. rerere 를 켜고 한 번 해결한 뒤, 병합을 되돌리고 다시 병합해 git 이 스스로
같은 해결을 적용하는 것을 확인합니다. 마지막으로 -X ours-s ours 를 각각 한 번씩
써서, 결과 파일에 무엇이 남고 무엇이 사라지는지를 내용으로 확인합니다.

공식 문서는 [git-rerere](https://git-scm.com/docs/git-rerere),
[git-merge](https://git-scm.com/docs/git-merge),
[git-config](https://git-scm.com/docs/git-config) 입니다.