← 홈Setup Tip

Setup Tip

Setup Tip — 충돌 없이 끝난 병합도 브랜치를 지울 수 있다

기능 브랜치에 기준 브랜치를 병합하고 충돌을 해결했는데 CI가 갑자기 대량으로 실패한다면, 테스트보다 병합 결과를 먼저 의심하라. 충돌 파일을 통째로 기준 브랜치 쪽으로 해결하면 브랜치의 변경이 조용히 사라진다. 브랜치가 건드린 파일마다 "병합 결과가 기준 브랜치와 바이트 단위로 같은가"를 확인하면 몇 초 만에 드러난다.

상황

오래 살아 있는 기능 브랜치를 최신 상태로 맞추려고 기준 브랜치를 병합한다. 충돌이 몇 개 나고, 사람이든 자동화된 작업자든 그것을 해결해 커밋한다. 병합 전 마지막 커밋에서는 CI가 초록이었는데, 병합 커밋부터 수명 주기 테스트 여러 개가 한꺼번에 빨갛게 변한다.

흔한 오진

기준 브랜치에서 들어온 새 코드와 기능 브랜치가 충돌하는 "진짜 호환성 문제"로 보고, 실패한 테스트를 하나씩 따라가며 고치기 시작한다. 혹은 테스트가 불안정하다고 보고 재실행을 누른다. 둘 다 병합 결과 자체가 무엇인지는 확인하지 않은 채 시간을 쓴다.

실제로 일어난 일

충돌이 난 핵심 파일 하나가 통째로 기준 브랜치 쪽 버전으로 해결되어 있었다. 병합 결과의 그 파일은 기준 브랜치의 같은 파일과 바이트 단위로 똑같았고, 기능 브랜치가 그 파일에 넣은 변경은 전부 사라졌다. 병합은 충돌 없이 "성공"했고 diff에도 경고가 없었다. 테스트는 사라진 기능을 정직하게 보고하고 있었을 뿐이다.

무엇을 확인해야 하는가

병합 기준점(merge base)과 병합 전 브랜치 끝 사이에서 브랜치가 건드린 파일 목록을 뽑는다. 그 파일 하나하나에 대해 병합 결과와 기준 브랜치의 내용이 완전히 같은지 비교한다. 같다면 그 파일에서 브랜치의 변경이 지워졌다는 뜻이다. 예: for f in $(git diff --name-only BASE BRANCH); do git diff --quiet MAIN MERGED -- "$f" && echo "DROPPED $f"; done. 브랜치가 일부러 자기 변경을 되돌린 경우가 아니라면, 출력이 한 줄이라도 있으면 병합은 잘못된 것이다.

고치는 방향

문제 병합을 되돌리기보다 병합 기준점에서 3자 병합을 다시 한다. 충돌마다 양쪽이 무엇을 바꿨는지 보고, 브랜치의 의도를 살리면서 기준 브랜치에서 새로 들어온 것(예: 새 import나 새 훅)만 얹는다. 다시 푸시하기 전에 위 검사로 DROPPED가 0인지, 이전 초록 커밋에 있던 기능이 돌아왔는지 확인한다.

확인 방법

병합 후 검사를 CI나 병합 작업 절차에 고정해 두면 사람의 주의력에 기대지 않아도 된다. 병합 전 마지막 초록 커밋과 새 병합 커밋에서 같은 테스트 묶음을 돌려 결과가 같은지, 그리고 브랜치가 건드린 파일 수가 병합 뒤에도 줄지 않았는지 숫자로 확인하고 끝낸다.