- Published on
Git rebase 충돌이 반복될 때 - rerere로 자동 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
git rebase를 자주 쓰는 팀이라면 이런 경험이 흔합니다.
- 기능 브랜치를 오래 끌다가 메인 브랜치 변경을 따라잡기 위해
rebase를 한다. - 충돌(conflict)이 발생해 수동으로 해결한다.
- 리뷰 반영/리베이스 정책/히스토리 정리 때문에 다시
rebase를 한다. - 똑같은 충돌이 또 난다. 그리고 또 같은 방식으로 해결한다.
이 반복 작업은 개발자의 집중력을 갉아먹고, 실수 확률도 올립니다. Git에는 이 문제를 정면으로 줄이는 기능이 있습니다. 바로 rerere(reuse recorded resolution) 입니다. 한 번 해결한 충돌의 “해결 결과”를 기록해두고, 다음에 동일(또는 충분히 유사)한 충돌이 나오면 자동으로 적용해주는 기능입니다.
이 글에서는 rerere의 동작 방식, 설정/운영 팁, 그리고 rebase 흐름에서 어떻게 체감 효과를 얻는지 실전 관점으로 설명합니다.
rerere란 무엇인가
rerere는 Git이 충돌이 발생했을 때 다음을 수행하도록 돕습니다.
- 충돌이 난 파일의 충돌 전후 상태(충돌 마커가 있는 형태) 를 저장
- 사용자가 충돌을 해결하고
git add로 스테이징하면 - Git이 그 해결 결과를 해결 레시피로 기록
- 이후 다른 커밋을 rebase/merge/cherry-pick 하다가 동일한 충돌 패턴이 나오면
- Git이 기록된 해결을 자동으로 재적용
즉, “충돌을 없애는 기능”이 아니라, 같은 충돌을 반복해서 풀지 않게 해주는 기능입니다.
어떤 상황에서 특히 효과가 큰가
- 리베이스를 여러 번 하는 브랜치(리뷰 피드백 반영, 메인 브랜치 잦은 업데이트)
- 체리픽(cherry-pick)으로 핫픽스를 여러 릴리즈 브랜치에 옮길 때
- 대규모 리팩터링 중 장기간 유지되는 기능 브랜치
- 동일 파일을 여러 브랜치가 지속적으로 만지는 모노레포 환경
rerere 활성화: 전역 설정부터
rerere는 기본적으로 꺼져 있는 경우가 많습니다. 전역으로 켜두면 대부분의 저장소에서 바로 효과를 봅니다.
# 전역 활성화
git config --global rerere.enabled true
# 자동으로 해결 적용까지 활성화(권장)
git config --global rerere.autoupdate true
rerere.enabled=true: 충돌 해결 기록을 저장rerere.autoupdate=true: 기록된 해결을 적용한 뒤, 해당 파일을 자동으로 스테이징까지 시도
> 팀 정책상 전역 설정이 부담이면 저장소 단위로만 설정해도 됩니다.
git config rerere.enabled true
git config rerere.autoupdate true
rebase에서 rerere가 어떻게 동작하는지
기본 흐름
- rebase 수행
git checkout feature
git fetch origin
git rebase origin/main
- 충돌 발생 → 수동 해결
# 충돌 파일 확인
git status
# 파일 열어서 충돌 해결 후
git add path/to/conflicted-file
- rebase 계속
git rebase --continue
여기서 중요한 포인트는: 충돌을 해결하고 git add하는 순간 rerere가 해결을 기록한다는 점입니다.
다음 rebase에서의 체감
같은 브랜치에서 다시:
git rebase origin/main
비슷한 충돌이 다시 나오면, rerere가 “이전에 네가 이렇게 풀었잖아”를 기억해서 자동 적용합니다. rerere.autoupdate=true라면 스테이징까지 되어 git rebase --continue만 치면 넘어가는 경우가 늘어납니다.
rerere 상태 확인과 운영 명령어
rerere가 기록을 쌓는 위치
기록은 저장소의 .git/rr-cache/에 저장됩니다. 이 디렉터리는 일반적으로 커밋 대상이 아니며, 로컬 개발 환경의 학습 캐시에 가깝습니다.
어떤 충돌이 기록/적용되었는지 보기
# rerere가 관리 중인 충돌 목록
git rerere status
# 어떤 파일에 어떤 해결을 적용했는지 로그
git rerere diff
캐시 정리
충돌 패턴이 너무 많이 쌓이거나, 잘못된 해결을 학습한 것 같을 때 정리가 필요합니다.
# 오래된 rerere 기록 정리
git rerere gc
특정 기록만 지우는 건 Git 버전/상황에 따라 수동으로 .git/rr-cache를 정리하는 방식이 필요할 수 있습니다. 팀에서 “이상한 자동 해결”이 반복된다면, 우선 git rerere status/diff로 어떤 해결이 적용되는지부터 확인하고, 필요 시 캐시를 비우는 것을 고려하세요.
실전 예시: 같은 충돌이 반복되는 전형적인 케이스
상황
main에서 함수 시그니처가 변경됨feature에서도 같은 파일을 수정함- rebase 때 충돌 발생
- 리뷰 반영으로 커밋을 수정하고 다시 rebase → 동일 충돌 재발
rerere 적용 전
- 매번 충돌 마커를 보고
- 어느 쪽 변경을 살릴지 판단하고
- 동일한 코드 편집을 반복
rerere 적용 후
첫 번째 충돌에서 한 번만 제대로 해결하고 git add하면, 이후 rebase에서는 동일 충돌이 재발해도 자동 적용될 확률이 높습니다.
이때 중요한 전제는 “충돌 형태가 충분히 유사”해야 한다는 것입니다. 파일 내용이 너무 많이 바뀌면 다른 충돌로 인식되어 적용되지 않을 수 있습니다.
rerere를 더 잘 쓰기 위한 팁
1) 충돌 해결은 ‘일관된 방식’으로
rerere는 해결을 재사용합니다. 즉, 첫 해결이 엉성하거나 임시방편이면 그 임시방편이 재사용될 수 있습니다.
- 첫 충돌 해결 시 테스트/빌드까지 확인
- 팀 합의된 머지 전략(예: main 우선, feature 우선, 혹은 수동 결합)을 유지
2) autoupdate를 켜되, 맹신하지 말 것
rerere.autoupdate=true는 생산성을 크게 올리지만, 자동 스테이징이 되었다고 해서 “정답”은 아닙니다.
- rebase 도중 자동 해결 적용 메시지를 봤다면
- 핵심 파일(서비스 로직, 마이그레이션, 인프라 설정 등)은 한 번 더 diff 확인
git diff --staged
3) rebase 정책이 강한 팀일수록 효과가 큼
히스토리를 깔끔하게 유지하려고 rebase를 자주 강제하는 팀(예: PR 머지 전 최신 main으로 rebase)은 충돌 반복이 더 잦습니다. rerere는 이런 문화에서 체감이 큽니다.
GitHub Actions처럼 CI에서 반복 실행/동시 실행 제어가 필요할 때도 결국 “반복을 줄이는 자동화”가 핵심인데, 맥락은 다르지만 접근은 유사합니다. 관련해서는 GitHub Actions 동시 실행 막힘 해결 - concurrency·cancel-in-progress도 함께 참고하면 좋습니다.
주의사항: 팀 공유/보안/재현성 관점
rerere 캐시는 기본적으로 로컬이다
.git/rr-cache는 보통 원격에 공유되지 않습니다. 즉,
- A 개발자가 학습한 해결이
- B 개발자에게 자동으로 전파되지는 않습니다.
팀 차원에서 공유하고 싶다면 별도의 워크플로(캐시 공유, 템플릿 저장소, 도구화)가 필요하지만, 일반적으로는 개인 생산성 향상으로만 써도 충분히 가치가 큽니다.
큰 리팩터링/대량 포맷팅 이후엔 적용률이 떨어질 수 있음
코드 포맷터 적용, 대규모 리네이밍 등으로 파일 맥락이 크게 바뀌면 “같은 충돌”로 인식되지 않아 rerere가 적용되지 않을 수 있습니다. 이 경우엔 충돌 자체를 줄이기 위해
- 리팩터링 PR을 먼저 머지하고
- 기능 브랜치 작업을 그 이후에 시작
같은 운영 전략이 더 효과적일 수 있습니다.
자동 해결이 ‘조용히’ 잘못될 가능성
rerere는 개발자가 과거에 했던 결정을 재사용합니다. 과거 결정이 지금도 옳다는 보장은 없습니다.
- 요구사항이 바뀌었거나
- main의 구현이 달라졌거나
- 충돌 해결 당시 임시로 처리했던 코드가 남아있다면
자동 적용은 오히려 버그를 재도입할 수 있습니다. 따라서 핵심 변경이 포함된 rebase에서는 git diff --staged, 테스트, 코드리뷰를 통해 안전장치를 유지하는 것이 좋습니다.
추천 워크플로: rebase + rerere 루틴
# 1) rerere 켜기(최초 1회)
git config --global rerere.enabled true
git config --global rerere.autoupdate true
# 2) 최신 main으로 rebase
git fetch origin
git rebase origin/main
# 3) 충돌 나면 한 번만 제대로 해결
# (에디터로 해결 후)
git add .
# 4) 계속 진행
git rebase --continue
# 5) 자동 해결이 적용된 구간은 스테이징 diff 확인(권장)
git diff --staged
이 루틴을 몇 번만 반복해도 “같은 충돌을 또 푸는 시간”이 눈에 띄게 줄어듭니다.
결론
git rerere는 rebase/merge/cherry-pick에서 반복되는 충돌 해결을 자동화해주는, 알고 나면 손에서 놓기 어려운 기능입니다. 특히 rebase 중심의 협업 문화에서는 충돌 자체를 없애기보다, 충돌 해결의 반복 비용을 줄이는 것이 더 현실적인 개선이 됩니다.
- 전역으로
rerere.enabled,rerere.autoupdate를 켜고 - 첫 충돌 해결을 신중하고 일관되게 하고
- 자동 적용된 결과는 핵심 구간에서만 빠르게 검증
이 3가지만 지켜도 rebase 스트레스가 확 내려갈 것입니다.