Git Rebase 마스터 가이드
Git Rebase: 커밋 히스토리를 재구성하는 강력한 도구
Section titled “Git Rebase: 커밋 히스토리를 재구성하는 강력한 도구”Git rebase는 브랜치의 베이스를 변경하고 커밋 히스토리를 재구성하는 Git의 가장 강력한 기능 중 하나입니다. 올바르게 사용하면 깔끔한 프로젝트 히스토리를 유지할 수 있지만, 잘못 사용하면 팀 전체의 워크플로우를 망칠 수 있는 양날의 검입니다.
이 가이드에서 다루는 내용
Section titled “이 가이드에서 다루는 내용”- Rebase의 핵심 개념과 동작 원리
- Merge vs Rebase: 언제 무엇을 사용해야 하는가
- Interactive Rebase를 통한 커밋 히스토리 조작
- 실무 시나리오별 rebase 활용법
- 위험 상황 대처법과 복구 전략
- 팀 협업을 위한 rebase 가이드라인
핵심 개념 이해하기
Section titled “핵심 개념 이해하기”Rebase vs Merge: 근본적인 차이
Section titled “Rebase vs Merge: 근본적인 차이”두 명령어 모두 브랜치를 통합하지만, 접근 방식이 완전히 다릅니다:
Merge 방식
Section titled “Merge 방식”git checkout featuregit merge mainRebase 방식
Section titled “Rebase 방식”git checkout featuregit rebase mainRebase의 동작 원리
Section titled “Rebase의 동작 원리”Rebase는 내부적으로 다음과 같은 단계로 동작합니다:
- 현재 브랜치의 커밋들을 임시 저장
- HEAD를 대상 브랜치로 이동
- 저장한 커밋들을 순서대로 재적용
# 내부 동작 시뮬레이션git checkout featuregit reset --hard main # HEAD를 main으로 이동git cherry-pick C D # 커밋들을 재적용기본 Rebase 사용법
Section titled “기본 Rebase 사용법”1. 브랜치 Rebase
Section titled “1. 브랜치 Rebase”가장 일반적인 사용 사례는 feature 브랜치를 최신 main 브랜치에 맞추는 것입니다:
# feature 브랜치를 main의 최신 상태로 rebasegit checkout featuregit rebase main
# 또는 한 줄로git rebase main feature2. 충돌 해결 워크플로우
Section titled “2. 충돌 해결 워크플로우”Rebase 중 충돌이 발생하면:
# 1. 충돌 파일 확인git status
# 2. 충돌 해결 후 스테이징git add <resolved-files>
# 3. Rebase 계속git rebase --continue
# 또는 중단하고 원래 상태로 복구git rebase --abort
# 현재 커밋 건너뛰기 (주의!)git rebase --skip3. Upstream Rebase
Section titled “3. Upstream Rebase”Fork한 저장소를 원본과 동기화할 때:
# upstream 설정 (최초 1회)git remote add upstream https://github.com/original/repo.git
# upstream 변경사항 가져오기git fetch upstream
# 로컬 main을 upstream/main으로 rebasegit checkout maingit rebase upstream/main
# feature 브랜치도 업데이트git checkout featuregit rebase mainInteractive Rebase 심화
Section titled “Interactive Rebase 심화”Interactive rebase는 커밋 히스토리를 수술하듯 정밀하게 조작할 수 있는 강력한 도구입니다.
기본 명령어
Section titled “기본 명령어”# 최근 3개 커밋 수정git rebase -i HEAD~3
# 특정 커밋 이후 모든 커밋 수정git rebase -i <commit-hash>
# 브랜치 분기점부터 수정git rebase -i mainInteractive 명령어 상세
Section titled “Interactive 명령어 상세”편집기에서 사용할 수 있는 명령어들:
| 명령어 | 약어 | 설명 | 사용 예시 |
|---|---|---|---|
pick | p | 커밋 유지 | 기본값, 변경 없이 사용 |
reword | r | 커밋 메시지만 수정 | 오타 수정, 메시지 개선 |
edit | e | 커밋 내용 수정 | 파일 추가/삭제, 코드 변경 |
squash | s | 이전 커밋과 합치기 | 여러 작은 커밋을 하나로 |
fixup | f | squash와 동일하나 메시지 버림 | 임시 커밋 정리 |
drop | d | 커밋 삭제 | 불필요한 커밋 제거 |
exec | x | 쉘 명령 실행 | 테스트 실행, 빌드 확인 |
1. 커밋 메시지 정리
Section titled “1. 커밋 메시지 정리”# git rebase -i HEAD~3 실행 후pick abc123 feat: Add user authenticationreword def456 fix: typo in login form # 'typo' → 'Fix typo'pick ghi789 feat: Add password reset2. 여러 커밋을 하나로 합치기
Section titled “2. 여러 커밋을 하나로 합치기”# 작업 중 생성된 지저분한 커밋들pick abc123 feat: Start implementing searchpick def456 WIP: search functionalitypick ghi789 fix typopick jkl012 finish search feature
# 정리 후pick abc123 feat: Start implementing searchsquash def456 WIP: search functionalitysquash ghi789 fix typosquash jkl012 finish search feature3. 커밋 순서 변경 및 삭제
Section titled “3. 커밋 순서 변경 및 삭제”# 원본pick abc123 feat: Add feature Apick def456 debug: console.log statementspick ghi789 feat: Add feature B
# 수정 후pick abc123 feat: Add feature Apick ghi789 feat: Add feature Bdrop def456 debug: console.log statements고급 Rebase 기법
Section titled “고급 Rebase 기법”1. Autosquash를 활용한 스마트 정리
Section titled “1. Autosquash를 활용한 스마트 정리”# fixup 커밋 생성git commit --fixup=abc123
# squash 커밋 생성git commit --squash=def456
# autosquash로 자동 정리git rebase -i --autosquash main2. Rebase with Exec
Section titled “2. Rebase with Exec”각 커밋마다 테스트를 실행하여 빌드가 깨지지 않는지 확인:
# rebase 시작git rebase -i main --exec "npm test"
# 편집기에서 자동으로 추가됨pick abc123 feat: Add featureexec npm testpick def456 fix: Bug fixexec npm test3. Preserve Merges
Section titled “3. Preserve Merges”병합 커밋을 유지하면서 rebase:
# 기존 병합 구조 유지 (Git 2.18 이전)git rebase --preserve-merges main
# Git 2.18 이상git rebase --rebase-merges main실무 시나리오별 가이드
Section titled “실무 시나리오별 가이드”시나리오 1: Pull Request 전 히스토리 정리
Section titled “시나리오 1: Pull Request 전 히스토리 정리”# 1. 작업 브랜치 확인git log --oneline main..feature
# 2. Interactive rebase 시작git rebase -i main
# 3. 커밋 정리# - 관련 커밋들을 squash# - 커밋 메시지 개선# - 불필요한 커밋 제거
# 4. 최종 확인git log --oneline --graph#!/bin/bashBRANCH=$(git branch --show-current)BASE_BRANCH=${1:-main}
echo "Cleaning up $BRANCH based on $BASE_BRANCH..."
# 백업 브랜치 생성git branch "${BRANCH}-backup"
# Interactive rebasegit rebase -i "$BASE_BRANCH" --autosquash
# 성공 여부 확인if [ $? -eq 0 ]; then echo "Cleanup successful!" echo "Backup saved as ${BRANCH}-backup"else echo "Rebase failed. Run 'git rebase --abort' to cancel"fi시나리오 2: 실수로 만든 커밋 수정
Section titled “시나리오 2: 실수로 만든 커밋 수정”# 방금 만든 커밋에 파일 추가git add forgotten-file.jsgit commit --amend --no-edit
# 이전 커밋에 변경사항 추가git add missing-changes.jsgit commit --fixup HEAD~2git rebase -i --autosquash HEAD~3시나리오 3: 다른 브랜치의 특정 커밋만 가져오기
Section titled “시나리오 3: 다른 브랜치의 특정 커밋만 가져오기”# Cherry-pick을 활용한 선택적 rebasegit rebase --onto main feature~3 feature
# 특정 범위의 커밋만 rebasegit rebase --onto newbase oldbase feature위험 상황과 복구 전략
Section titled “위험 상황과 복구 전략”1. Rebase 후 Force Push
Section titled “1. Rebase 후 Force Push”# 안전한 force pushgit push --force-with-lease origin feature
# 일반 force push (주의!)git push --force origin feature
# force-with-lease가 더 안전한 이유:# 원격에 다른 변경사항이 있으면 거부됨2. 잘못된 Rebase 복구
Section titled “2. 잘못된 Rebase 복구”# reflog 확인git reflog
# rebase 이전 상태 찾기# 예: abc123 HEAD@{5}: checkout: moving from feature to main
# 복구git reset --hard HEAD@{5}# rebase 전 백업 생성 (습관화 추천)git branch backup-feature
# rebase 수행git rebase main
# 문제 발생 시 복구git reset --hard backup-feature3. 공개된 브랜치 Rebase 수습
Section titled “3. 공개된 브랜치 Rebase 수습”최악의 상황: 이미 push된 브랜치를 rebase했을 때
# 팀에게 즉시 알리고 다음 수행
# 옵션 1: revert the rebasegit refloggit reset --hard <rebase-이전-commit>git push --force-with-lease
# 옵션 2: 팀원들의 로컬 수정# 각 팀원이 실행git fetch origingit rebase origin/feature # 또는git reset --hard origin/feature팀 협업 가이드라인
Section titled “팀 협업 가이드라인”Rebase 정책 수립
Section titled “Rebase 정책 수립”# .gitmessage 또는 README에 명시할 내용
## 우리 팀의 Rebase 규칙
### ✅ Rebase 사용 가능- 아직 push하지 않은 로컬 커밋- 자신만 작업하는 feature 브랜치- PR 리뷰 전 히스토리 정리
### ❌ Rebase 금지- main, develop 등 공용 브랜치- 다른 사람과 공유 중인 브랜치- 이미 PR이 열린 브랜치 (리뷰어와 협의 필요)
### 🔧 권장 워크플로우1. feature 브랜치에서 작업2. PR 생성 전 interactive rebase로 정리3. main의 변경사항은 rebase로 통합4. PR 머지는 squash merge 사용Git Hooks로 안전장치 구현
Section titled “Git Hooks로 안전장치 구현”#!/bin/bash# .git/hooks/pre-rebase
protected_branches="main|develop|release/*"current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
if [[ "$current_branch" =~ $protected_branches ]]; then echo "⚠️ Rebase on protected branch '$current_branch' is not allowed!" echo "Please create a feature branch for your changes." exit 1fi
# 원격에 존재하는지 확인if git ls-remote --exit-code --heads origin "$current_branch" >/dev/null 2>&1; then echo "⚠️ Warning: Branch '$current_branch' exists on remote." echo "Rebase will rewrite history. Make sure to coordinate with your team!" read -p "Continue? (y/N) " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fifiBest Practices 체크리스트
Section titled “Best Practices 체크리스트”✅ 항상 지켜야 할 원칙
Section titled “✅ 항상 지켜야 할 원칙”📊 Rebase vs Merge 의사결정 트리
Section titled “📊 Rebase vs Merge 의사결정 트리”실전 연습 문제
Section titled “실전 연습 문제”연습 1: 지저분한 히스토리 정리
Section titled “연습 1: 지저분한 히스토리 정리”# 연습용 저장소 생성mkdir rebase-practice && cd rebase-practicegit init
# 지저분한 히스토리 생성echo "initial" > file.txt && git add . && git commit -m "Initial commit"echo "feature start" >> file.txt && git add . && git commit -m "WIP: feature"echo "typo" >> file.txt && git add . && git commit -m "fix typu"echo "more work" >> file.txt && git add . && git commit -m "more changes"echo "done" >> file.txt && git add . && git commit -m "feature complete"
# 과제: 위 5개 커밋을 의미있는 2개 커밋으로 정리# 힌트: git rebase -i HEAD~4연습 2: 충돌 해결 연습
Section titled “연습 2: 충돌 해결 연습”# main 브랜치 설정git checkout -b mainecho "main line 1" > conflict.txtgit add . && git commit -m "Main commit"
# feature 브랜치 생성git checkout -b feature HEAD~1echo "feature line 1" > conflict.txtgit add . && git commit -m "Feature commit"
# main에 추가 커밋git checkout mainecho "main line 2" >> conflict.txtgit add . && git commit -m "Main update"
# rebase 시도 (충돌 발생)git checkout featuregit rebase main
# 과제: 충돌을 해결하고 rebase 완료하기Git rebase는 강력한 도구이지만, 큰 힘에는 큰 책임이 따릅니다. 이 가이드의 핵심 교훈:
- 로컬에서는 자유롭게, 원격에서는 신중하게
- 백업은 선택이 아닌 필수
- 팀과의 소통이 가장 중요
- 연습을 통해 자신감 쌓기