- Published on
Git rebase 충돌 자동 해결 - rerere 실무 설정
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
git rebase를 자주 쓰는 팀이라면 “비슷한 충돌을 또 푸는” 일이 반복됩니다. 예를 들어 develop에서 기능 브랜치를 오래 끌고 가다가 매번 같은 파일의 같은 구간이 충돌 나고, 해결 방식도 늘 동일한 경우가 많습니다. 이때 Git의 rerere(reuse recorded resolution) 기능을 켜두면, 한 번 해결한 충돌을 Git이 기록해두었다가 다음에 동일/유사 충돌이 발생했을 때 자동으로 해결안을 재적용합니다.
rerere는 마법이 아니라 “충돌 난 전/후 상태를 해시로 저장해 두고 재사용”하는 메커니즘입니다. 잘 쓰면 rebase 시간이 체감상 크게 줄어들지만, 팀 정책/리포지토리 상태에 따라 부작용도 생길 수 있어 올바른 설정과 운영 규칙이 중요합니다.
이 글에서는 rerere의 동작 원리, 개인/팀에서의 권장 설정, rebase 워크플로우에 녹이는 방법, 그리고 실무에서 자주 겪는 함정과 점검 방법을 정리합니다.
rerere가 해결하는 문제: “반복 충돌”
다음 상황에서 rerere 효과가 큽니다.
- 장수 브랜치(오래 유지되는 feature/hotfix)에서
rebase를 반복 develop/main에서 리팩터링이 잦고, 기능 브랜치가 자주 따라가야 함- 포맷터/린터 적용으로 동일 파일의 동일 영역에서 충돌이 반복
- 동일한 충돌 패턴이 여러 커밋에 걸쳐 연쇄적으로 발생(특히
rebase --onto)
반대로, 충돌이 매번 “의미적으로” 다르게 해결되어야 하는 영역(예: 요구사항이 바뀌어 선택지가 달라지는 로직)이라면 rerere가 자동 적용한 결과를 그대로 믿으면 위험합니다. rerere는 정답을 추론하지 않고, 과거에 사용자가 선택한 해결안을 재사용할 뿐입니다.
rerere 동작 원리(핵심만)
rerere는 충돌이 발생했을 때:
- 충돌 난 파일의 충돌 마커(<<<<<<<, =======, >>>>>>>) 를 포함한 상태를 수집
- 충돌의 “우리/그들” 버전 조각을 기반으로 ID(해시) 를 생성
- 사용자가 충돌을 해결하고
git add하면, 그 해결 결과를.git/rr-cache/에 저장 - 이후 동일한 충돌 ID가 다시 나타나면, 저장된 해결 결과를 워킹트리에 자동 적용
즉, rerere는 “파일 전체”가 아니라 충돌 덩어리(hunk) 단위로 재사용합니다. 그래서 파일의 다른 부분이 바뀌어도 충돌 조각이 유사하면 적용될 수 있습니다.
실무 권장 설정: 개인 기본값
1) rerere 활성화
가장 기본은 아래 한 줄입니다.
git config --global rerere.enabled true
이후 충돌을 한 번 해결하고 git add 하면 기록이 쌓입니다.
2) 자동 업데이트(권장)
rerere는 기본적으로 “적용 가능한 해결안이 있으면 적용”하지만, 상황에 따라 기록을 더 잘 쌓게 하려면 autoupdate를 켜는 편이 실무에서 편합니다.
git config --global rerere.autoupdate true
autoupdate=true: rerere가 해결안을 적용한 뒤, 해당 파일을 자동으로 stage까지 해주려는 동작을 포함합니다(상황에 따라 다르게 체감될 수 있음).- 팀에 따라 “자동 stage는 싫다”면
false로 두고, 적용만 받고 직접 검토 후git add하는 방식도 가능합니다.
3) rebase 시 충돌 재현을 줄이는 보조 옵션
rerere 자체 옵션은 아니지만, rebase 경험을 개선하는데 자주 같이 씁니다.
# rebase 중 stash 자동 처리(로컬 변경이 있을 때)
git config --global rebase.autoStash true
# 충돌 시 3-way merge를 더 잘 활용(상황에 따라 유용)
git config --global merge.conflictStyle zdiff3
merge.conflictStyle=zdiff3는 충돌 마커에 “베이스” 컨텍스트가 더 보여서, 사람이 검토할 때 실수가 줄어듭니다.
팀/조직에서의 운영 포인트: rr-cache를 공유할 것인가?
결론부터: 보통은 “공유하지 않음”이 안전
rerere 캐시는 기본적으로 .git/rr-cache/에 저장되며, Git이 자동으로 커밋/푸시하는 대상이 아닙니다. 이를 팀끼리 공유하면 모두가 같은 충돌을 더 빨리 해결할 수 있을 것 같지만, 실무에서는 다음 리스크가 있습니다.
- 누군가의 “임시 해결”이 팀 표준처럼 전파될 수 있음
- 충돌 해결은 종종 도메인 의사결정(어느 로직을 살릴지)이 포함되는데, 캐시 공유는 그 의사결정의 맥락을 전달하지 못함
- 다른 브랜치/다른 히스토리에서 해시가 우연히 맞아 잘못 적용될 가능성(낮지만 0은 아님)
따라서 일반적으로는:
- 개인 로컬에서 rerere를 활성화하고,
- PR 리뷰/테스트로 결과를 검증하며,
- “반복 충돌”을 개인 생산성 향상 도구로 활용
하는 접근이 무난합니다.
예외: 대규모 모노레포 + 중앙 머지 담당
중앙에서 머지/리베이스를 담당하는 소수의 인원이 있고, 충돌 해결이 표준화되어 있으며, CI가 강력한 조직이라면 rr-cache 공유를 고려할 수 있습니다. 다만 이 경우에도 rr-cache를 그대로 버전관리하기보다는 “머지 봇/전담 머신의 캐시”로 운영하는 편이 일반적입니다.
rebase 워크플로우에 rerere 녹이기
1) 기본 rebase 흐름
# 최신 main을 기준으로 feature 브랜치를 재정렬
git fetch origin
git checkout feature/my-work
git rebase origin/main
충돌이 나면:
# 충돌 해결(에디터/머지툴)
# ...
git status
# 해결 완료한 파일 stage
git add path/to/conflicted-file
# rebase 계속
git rebase --continue
이때 rerere가 켜져 있으면, 처음 한 번 해결한 충돌은 rr-cache에 기록되고, 이후 같은 패턴의 충돌이 등장하면 자동으로 적용됩니다.
2) “연쇄 충돌”에서 진가가 나오는 패턴
리베이스 중 다음 커밋에서도 똑같은 파일/구간이 다시 충돌하는 경우가 많습니다.
- 커밋 A: 함수 시그니처 변경
- 커밋 B: 같은 함수 호출부 수정
- main: 이미 다른 방식으로 함수가 바뀜
이때 첫 충돌을 사람이 정확히 풀고 나면, B에서 발생하는 유사 충돌은 rerere가 상당 부분 자동으로 풀어줍니다.
3) rerere가 적용됐는지 확인하는 방법
rebase 도중 메시지로 힌트를 주는 경우도 있지만, 가장 확실한 건 상태 확인입니다.
git status
- 충돌 파일이 “both modified”에서 사라지고 stage되어 있으면(autoupdate 켠 경우) rerere 적용 가능성이 큽니다.
- 그래도 반드시
git diff로 결과를 확인하세요.
실무에서 자주 하는 실수와 방지책
1) “자동 해결”을 무검토로 넘김
rerere는 과거 해결안을 그대로 재사용합니다. 과거의 해결이 지금도 옳다는 보장은 없습니다.
권장 습관:
# rebase 중간중간 결과 확인
git diff
# 커밋 단위 확인(리베이스라면 HEAD가 계속 변함)
git show --stat
2) 큰 리팩터링 직후에는 캐시가 오히려 혼란을 줄 수 있음
대규모 리팩터링(파일 이동/함수 분해/포맷 전면 적용) 이후에는 충돌 패턴이 “비슷해 보이지만 의미가 달라지는” 케이스가 늘어납니다. 이 시기에는 rerere 적용 결과를 더 엄격히 리뷰하거나, 필요하면 rerere를 일시적으로 끄는 것도 방법입니다.
# 현재 리포지토리에서만 rerere 끄기
git config rerere.enabled false
3) rr-cache가 비대해짐
오래 쓰다 보면 .git/rr-cache가 커질 수 있습니다. 일반적으로 큰 문제는 아니지만, 디스크/백업 정책이 빡빡한 환경에서는 점검 대상입니다.
- 주기적으로
.git디렉터리 크기 확인 - 필요 시 캐시 정리(정리 전에는 왜 정리하는지 합의가 필요)
rerere와 함께 알아두면 좋은 “되돌리기” 안전장치
rebase는 히스토리를 바꾸므로 실수했을 때 복구 루틴이 중요합니다. rerere로 충돌이 자동 적용되면 “내가 뭘 했는지” 감각이 흐려질 수 있어, 복구 방법을 더 확실히 알고 있어야 합니다.
- rebase 후 강제 푸시까지 갔는데 꼬였을 때는
reflog가 마지막 보루입니다. - 관련 내용은 아래 글을 함께 보면 좋습니다.
Git rebase 후 강제푸시 충돌? reflog로 복구하기
CI/CD 환경에서의 팁: 충돌을 줄이는 운영 전략
rerere는 “충돌 해결 비용”을 줄이지만, 애초에 충돌이 덜 나게 운영하는 것도 중요합니다.
- 브랜치 수명을 짧게: 작은 단위로 자주 머지
- 포맷터/린터는 한 번에 몰아서 적용(대규모 포맷 커밋은 별도 PR로)
- GitHub Actions에서 배포/머지 타이밍이 꼬이면 불필요한 리베이스가 늘어납니다. 동시성 제어도 같이 챙기면 좋습니다.
GitHub Actions 동시성 꼬임으로 배포 겹침 막기
추천 실무 설정 예시(복붙용)
아래는 “개인 개발 머신에서 rerere를 적극 활용”하는 기준의 예시입니다.
# rerere 켜기
git config --global rerere.enabled true
# 자동 적용/업데이트(원치 않으면 false)
git config --global rerere.autoupdate true
# rebase 편의
git config --global rebase.autoStash true
# 충돌 마커에 base까지 보여서 판단 쉽게
git config --global merge.conflictStyle zdiff3
# (선택) 기본 브랜치 이름에 맞게 pull 전략을 명확히
# git config --global pull.rebase true
추가로, 특정 리포지토리에서만 켜고 싶다면 --global을 빼고 해당 repo에서만 설정하면 됩니다.
결론
rerere는 rebase를 많이 하는 팀에서 “반복 충돌”을 체계적으로 줄여주는 기능입니다. 핵심은 단순합니다.
- 한 번 제대로 해결하면
- Git이 그 해결을 기록하고
- 다음부터는 자동 재적용한다
다만 자동 적용은 어디까지나 과거의 선택을 재사용하는 것이므로, git diff/테스트/리뷰로 결과를 검증하는 습관이 함께 가야 합니다. 개인 환경에서 우선 활성화해 체감 효과를 확인한 뒤, 팀 워크플로우(리베이스 빈도, 브랜치 정책, CI 강도)에 맞춰 운영 규칙을 다듬는 것이 가장 현실적인 도입 방식입니다.