# Git Rebase 완벽 가이드: Merge와의 차이점부터 Interactive Rebase까지
Table of Contents
“Rebase 하다가 커밋 다 날렸어요.”
Git을 사용하다 보면 한 번쯤 듣거나 경험하는 공포의 순간입니다. Rebase는 강력하지만, 잘못 사용하면 작업을 잃을 수 있어서 많은 개발자가 두려워합니다. 하지만 제대로 이해하면 이보다 유용한 도구도 없습니다.
이 글에서는 Rebase가 실제로 무엇을 하는지, Merge와 어떻게 다른지, 그리고 언제 어떤 것을 선택해야 하는지 명확하게 설명합니다. Interactive Rebase로 커밋을 정리하는 방법까지 실전 중심으로 다룹니다.
Rebase란 무엇인가?
Rebase는 말 그대로 “베이스를 다시 설정”하는 것입니다. 브랜치의 기반(base)을 다른 커밋으로 옮깁니다.
시각적 이해
현재 상황:
A---B---C feature
/
D---E---F---G main
git rebase main을 실행하면:
A'--B'--C' feature
/
D---E---F---G main
feature 브랜치의 커밋들(A, B, C)이 main의 최신 커밋(G) 위에 다시 적용됩니다. 커밋 A’, B’, C’는 내용은 같지만 새로운 커밋입니다 (해시가 다름).
Merge와의 차이
같은 상황에서 git merge main을 실행하면:
A---B---C---M feature
/ /
D---E---F---G---- main
Merge는 **병합 커밋(M)**을 생성하여 두 브랜치의 히스토리를 합칩니다. 원본 커밋은 그대로 유지됩니다.
핵심 차이점 정리
| 특성 | Rebase | Merge |
|---|---|---|
| 히스토리 | 선형(linear) | 분기 유지 |
| 원본 커밋 | 새 커밋으로 대체 | 그대로 유지 |
| 병합 커밋 | 없음 | 생성 |
| 충돌 해결 | 커밋마다 개별 해결 | 한 번에 해결 |
| 협업 위험 | 공유된 브랜치에서 위험 | 안전 |
언제 Rebase를 사용하는가?
1. 로컬 브랜치를 최신화할 때
# feature 브랜치에서 작업 중
git fetch origin
git rebase origin/main
main의 최신 변경사항을 가져오면서 깔끔한 히스토리를 유지합니다.
2. PR(Pull Request) 전 커밋 정리
# 최근 5개 커밋을 정리
git rebase -i HEAD~5
“WIP”, “fix typo” 같은 임시 커밋을 squash하여 의미 있는 단위로 만듭니다.
3. 충돌을 커밋 단위로 해결하고 싶을 때
Merge는 모든 충돌을 한 번에 보여주지만, Rebase는 커밋별로 충돌을 해결합니다. 복잡한 충돌에서는 이 방식이 더 관리하기 쉬울 수 있습니다.
4. 깔끔한 git log를 원할 때
# Rebase 후
* abc1234 feat: 사용자 인증 기능 추가
* def5678 fix: 로그인 버그 수정
* ghi9012 refactor: 코드 정리
# Merge 후
* abc1234 Merge branch 'main' into feature
|
| * def5678 main의 변경사항
* | ghi9012 feature의 변경사항
|/
Rebase는 선형 히스토리를 만들어 git log와 git bisect가 더 깔끔합니다.
언제 Rebase를 피해야 하는가?
:::warning 황금률: 이미 푸시한 커밋은 Rebase하지 마세요. :::
공유된 브랜치에서 Rebase하면 안 되는 이유
# 팀원 A가 feature 브랜치를 푸시
git push origin feature
# 팀원 B가 feature 브랜치를 pull
git pull origin feature
# 팀원 A가 rebase 후 force push
git rebase main
git push --force origin feature # 위험!
# 팀원 B가 push하려고 하면...
git push origin feature
# error: 히스토리가 다름!
팀원 B의 로컬 커밋과 원격의 커밋이 달라져서 충돌과 혼란이 발생합니다.
Merge를 사용해야 하는 경우
- 공유된 브랜치 (main, develop 등)
- PR을 머지할 때 (대부분의 Git 호스팅 서비스 기본값)
- 히스토리 보존이 중요할 때 (언제 무엇이 병합되었는지)
기본 Rebase 사용법
브랜치 최신화
# feature 브랜치에서
git checkout feature
# main의 최신 커밋 위로 rebase
git rebase main
원격 브랜치로 rebase
git fetch origin
git rebase origin/main
Rebase 중 충돌 해결
git rebase main
# CONFLICT 발생
# 충돌 파일 수정 후
git add <충돌파일>
git rebase --continue
# 또는 해당 커밋 건너뛰기
git rebase --skip
# 또는 rebase 취소
git rebase --abort
--abort는 rebase 시작 전 상태로 완전히 되돌립니다. 언제든 안전하게 사용할 수 있습니다.
Interactive Rebase 완전 정복
Interactive Rebase(-i)는 커밋을 수정, 합치기, 삭제, 순서 변경할 수 있는 강력한 도구입니다.
기본 사용법
# 최근 3개 커밋을 편집
git rebase -i HEAD~3
에디터가 열리면:
pick abc1234 첫 번째 커밋
pick def5678 두 번째 커밋
pick ghi9012 세 번째 커밋
# Commands:
# p, pick = 커밋 사용
# r, reword = 커밋 사용, 메시지 수정
# e, edit = 커밋 사용, 수정을 위해 중지
# s, squash = 이전 커밋과 합치기, 메시지 합침
# f, fixup = squash와 같지만 메시지 버림
# d, drop = 커밋 삭제
커밋 메시지 수정 (reword)
git rebase -i HEAD~3
reword abc1234 오타가 있는 커밋 메시지
pick def5678 두 번째 커밋
pick ghi9012 세 번째 커밋
저장 후 새 에디터가 열리면 메시지를 수정합니다.
커밋 합치기 (squash/fixup)
여러 개의 임시 커밋을 하나로 합칩니다.
git rebase -i HEAD~4
변경 전:
pick abc1234 feat: 사용자 인증 추가
pick def5678 WIP
pick ghi9012 fix typo
pick jkl3456 WIP 2
변경 후:
pick abc1234 feat: 사용자 인증 추가
fixup def5678 WIP
fixup ghi9012 fix typo
fixup jkl3456 WIP 2
결과: 4개의 커밋이 1개로 합쳐집니다.
squash vs fixup:
squash: 커밋 메시지를 합침 (편집 기회 있음)fixup: 이전 커밋의 메시지만 유지 (더 간단)
커밋 순서 변경
pick ghi9012 세 번째 커밋
pick abc1234 첫 번째 커밋
pick def5678 두 번째 커밋
줄 순서를 바꾸면 커밋 순서가 변경됩니다.
커밋 분할 (edit)
하나의 큰 커밋을 여러 개로 나눕니다.
git rebase -i HEAD~2
edit abc1234 너무 큰 커밋
pick def5678 다음 커밋
저장 후:
# 커밋을 취소하고 변경사항을 스테이징 영역에 유지
git reset HEAD~
# 원하는 단위로 나누어 커밋
git add file1.js
git commit -m "feat: 첫 번째 기능"
git add file2.js
git commit -m "feat: 두 번째 기능"
# rebase 계속
git rebase --continue
자동 squash 설정
커밋 메시지에 fixup! 또는 squash!를 붙이면 자동으로 정렬됩니다.
# 원본 커밋
git commit -m "feat: 사용자 인증"
# 수정사항을 fixup 커밋으로
git commit -m "fixup! feat: 사용자 인증"
# --autosquash 옵션으로 rebase
git rebase -i --autosquash HEAD~3
자동으로 fixup 커밋이 원본 아래에 배치됩니다.
글로벌 설정:
git config --global rebase.autosquash true
실전 워크플로우
워크플로우 1: Feature Branch Workflow
# 1. feature 브랜치 생성
git checkout -b feature/user-auth main
# 2. 작업 및 커밋
git commit -m "WIP: 로그인 폼"
git commit -m "WIP: 로그인 API 연동"
git commit -m "fix: 버그 수정"
git commit -m "WIP: 완료"
# 3. main 최신화
git fetch origin
git rebase origin/main
# 4. 커밋 정리
git rebase -i HEAD~4
# 4개의 WIP 커밋을 1개로 squash
# 5. PR 생성 후 merge
워크플로우 2: 장기 실행 브랜치 관리
# develop 브랜치를 main으로 정기적으로 rebase (개인 브랜치인 경우)
git checkout develop
git rebase main
# 또는 main의 변경사항을 merge (팀 공유 브랜치인 경우)
git checkout develop
git merge main
워크플로우 3: 코드 리뷰 피드백 반영
# PR 피드백 반영 후
git commit -m "fixup! feat: 사용자 인증"
# 리뷰어가 승인하면 squash하여 push
git rebase -i --autosquash HEAD~3
git push --force-with-lease origin feature/user-auth
--force-with-lease는 --force보다 안전합니다. 원격에 예상치 못한 변경이 있으면 push를 거부합니다.
충돌 해결 전략
Rebase 충돌 vs Merge 충돌
Merge: 모든 충돌이 한 번에 발생
git merge main
# 충돌 해결
git add .
git commit
Rebase: 커밋마다 충돌 발생 가능
git rebase main
# 첫 번째 커밋 충돌 해결
git add .
git rebase --continue
# 두 번째 커밋 충돌 해결
git add .
git rebase --continue
# ...
충돌 최소화 전략
- 자주 rebase하기: 변경이 적을 때 자주 하면 충돌도 적습니다.
- 작은 커밋 단위: 큰 커밋보다 작은 커밋이 충돌 해결이 쉽습니다.
- rerere 활성화: 같은 충돌을 자동으로 해결합니다.
git config --global rerere.enabled true
충돌 시 유용한 도구
# 충돌 상태 확인
git status
# 3-way diff 도구 실행
git mergetool
# 특정 버전 선택
git checkout --ours <file> # 현재 브랜치 버전
git checkout --theirs <file> # rebase 대상 브랜치 버전
위험 상황과 복구
실수로 rebase한 경우 복구
# reflog에서 이전 상태 찾기
git reflog
# abc1234 HEAD@{0}: rebase finished
# def5678 HEAD@{1}: rebase: checkout main
# ghi9012 HEAD@{2}: commit: 마지막 작업
# 이전 상태로 복구
git reset --hard ghi9012
reflog는 HEAD의 모든 이동을 기록합니다. 거의 모든 상황에서 복구할 수 있습니다.
Force push 후 팀원이 영향받은 경우
# 팀원이 해야 할 일
git fetch origin
# 로컬 변경사항이 없으면
git reset --hard origin/feature
# 로컬 변경사항이 있으면
git stash
git reset --hard origin/feature
git stash pop
예방 설정
# force push 시 경고
git config --global push.default simple
# main/master 브랜치 force push 금지 (서버 설정)
# GitHub/GitLab의 branch protection rules 사용
Rebase vs Merge: 팀 전략 선택
Rebase 중심 전략
장점:
- 깔끔한 선형 히스토리
git log,git bisect가 쉬움- PR당 하나의 의미 있는 커밋
단점:
- force push 필요
- 팀원 교육 필요
- 실수 시 복구가 복잡
적합한 팀: 소규모, 숙련된 개발자
Merge 중심 전략
장점:
- 안전하고 예측 가능
- 모든 히스토리 보존
- 초보자도 쉽게 사용
단점:
- 복잡한 히스토리 그래프
- 불필요한 merge 커밋 증가
적합한 팀: 대규모, 다양한 숙련도
하이브리드 전략 (권장)
로컬 작업: Rebase로 정리
PR 병합: Squash and Merge
규칙:
1. 개인 브랜치에서만 rebase
2. 공유 브랜치는 merge만
3. PR은 squash merge로 1커밋화
GitHub/GitLab 설정:
- Squash and Merge를 기본값으로 설정
- Rebase and Merge 옵션도 허용
유용한 Git 설정
# pull 시 자동 rebase
git config --global pull.rebase true
# autostash (rebase 전 자동 stash)
git config --global rebase.autoStash true
# autosquash
git config --global rebase.autosquash true
# rerere (충돌 해결 기억)
git config --global rerere.enabled true
# 기본 에디터 설정
git config --global core.editor "code --wait"
정리
Git Rebase의 핵심 포인트:
- Rebase는 커밋을 새로 만듭니다. 원본 커밋의 해시가 변경됩니다.
- 푸시한 커밋은 rebase하지 마세요. 팀원에게 혼란을 줍니다.
- Interactive Rebase로 커밋을 정리하세요. squash, fixup으로 의미 있는 단위로 만듭니다.
--force-with-lease를 사용하세요.--force보다 안전합니다.- reflog는 당신의 친구입니다. 실수해도 거의 항상 복구할 수 있습니다.
- 팀 규칙을 정하세요. Rebase와 Merge를 언제 사용할지 합의합니다.
Rebase는 처음엔 두렵지만, 이해하고 나면 Git을 훨씬 효과적으로 사용할 수 있습니다. 개인 브랜치에서 충분히 연습한 후, 팀 워크플로우에 적용해보세요. 깔끔한 히스토리의 가치를 체감하게 될 것입니다.