git rebase와 git merge의 차이를 이해하는 것은 모든 Git 개발자에게 필수적입니다.
Git Merge 작동 원리
Git merge는 두 부모 커밋을 가진 새로운 머지 커밋을 만듭니다.
main 브랜치에서 git merge feature를 실행하면 공통 조상을 찾습니다.
Git Rebase 작동 원리
Git rebase는 커밋을 다른 브랜치의 끝으로 이동하여 히스토리를 다시 씁니다.
feature 브랜치에서 git rebase main을 실행하면 커밋이 하나씩 다시 적용됩니다.
시각적 비교
BEFORE (both branches have diverged from common ancestor C2):
C5---C6---C7 (feature)
/
C1---C2---C3---C4 (main)
AFTER git merge feature (from main):
C5---C6---C7
/ \
C1---C2---C3---C4----M8 (main) ← merge commit M8 has 2 parents
(feature still points to C7)
AFTER git rebase main (from feature):
C1---C2---C3---C4 (main)
\
C5'---C6'---C7' (feature) ← new commits (different SHAs)
Then fast-forward merge:
C1---C2---C3---C4---C5'---C6'---C7' (main, feature) ← linear history기능 비교
| 항목 | git merge | git rebase |
|---|---|---|
| 히스토리 | 모든 히스토리 보존 | 선형 히스토리 |
| 커밋 SHA | 원본 SHA 보존 | 새 SHA 생성 |
| 안전성 | 비파괴적 | 파괴적 |
| 충돌 해결 | 머지 커밋에서 한 번에 해결 | 커밋별로 해결 |
| 팀 친화적 | 공유 브랜치에 안전 | 공유 브랜치에 위험 |
| 되돌리기 | 쉬움 | 어려움 |
| git bisect | 머지 커밋으로 노이즈 | 깔끔한 히스토리로 유용 |
| 그래프 시각화 | 복잡한 그래프 | 깔끔한 단일 선 |
Git Merge 상세
패스트포워드 머지
대상 브랜치에 새 커밋이 없을 때.
# Fast-forward merge (no merge commit created)
git checkout main
git merge feature
# Before:
# C1---C2 (main)
# \
# C3---C4 (feature)
# After:
# C1---C2---C3---C4 (main, feature)
# main pointer simply moved forward3-way 머지
두 브랜치가 모두 분기했을 때.
# Three-way merge (creates merge commit)
git checkout main
git merge feature
# Before:
# C3---C4 (feature)
# /
# C1---C2---C5---C6 (main)
# After:
# C3---C4
# / \
# C1---C2---C5---C6---M7 (main) ← merge commit M7--no-ff
패스트포워드가 가능해도 머지 커밋을 강제.
# Force merge commit even when fast-forward is possible
git checkout main
git merge --no-ff feature
# Before:
# C1---C2 (main)
# \
# C3---C4 (feature)
# After (with --no-ff):
# C1---C2---------M5 (main) ← merge commit preserves branch history
# \ /
# C3---C4 (feature)
# After (without --no-ff, default):
# C1---C2---C3---C4 (main, feature) ← no evidence of branchGit Rebase 상세
기본 Rebase
표준 rebase는 커밋을 대상 브랜치 위에 다시 적용합니다.
# Basic rebase workflow
git checkout feature
git rebase main
# Before:
# C3---C4 (feature)
# /
# C1---C2---C5---C6 (main)
# After rebase:
# C3'---C4' (feature) ← new commits!
# /
# C1---C2---C5---C6 (main)
# Then merge (fast-forward):
git checkout main
git merge feature
# C1---C2---C5---C6---C3'---C4' (main, feature) ← linear!인터랙티브 Rebase
커밋 수정, 스쿼시, 재정렬, 삭제가 가능.
# Interactive rebase - clean up last 4 commits
git rebase -i HEAD~4
# Editor opens with:
pick abc1234 Add user model
pick def5678 Fix typo in user model
pick ghi9012 Add user validation
pick jkl3456 Fix validation edge case
# Change to:
pick abc1234 Add user model
fixup def5678 Fix typo in user model # squash into previous, discard message
pick ghi9012 Add user validation
fixup jkl3456 Fix validation edge case # squash into previous, discard message
# Result: 2 clean commits instead of 4
# "Add user model" (includes typo fix)
# "Add user validation" (includes edge case fix)
# Interactive rebase commands:
# pick = use commit as-is
# reword = use commit but edit message
# edit = use commit but stop for amending
# squash = meld into previous commit (keep message)
# fixup = meld into previous commit (discard message)
# drop = remove commit entirely--onto Rebase
커밋 서브셋을 다른 베이스에 rebase.
# --onto: Move a branch to a different base
# Scenario: feature-b was branched from feature-a by mistake
# You want feature-b based on main instead
# D---E (feature-b)
# /
# A---B---C (feature-a)
# |
# F---G (main)
git rebase --onto main feature-a feature-b
# Result:
# D'---E' (feature-b) ← now based on main
# /
# A---B---C (feature-a)
# |
# F---G (main)충돌 해결
merge와 rebase 모두 충돌이 발생할 수 있습니다.
Merge 충돌
모든 충돌이 한 번에 표시됩니다.
# Merge conflict workflow
git checkout main
git merge feature
# CONFLICT (content): Merge conflict in src/app.ts
# Automatic merge failed; fix conflicts and then commit
# 1. Open conflicting files and resolve
# 2. Stage resolved files
git add src/app.ts
# 3. Complete the merge
git commit # creates merge commit with conflict resolution
# Abort merge if needed
git merge --abortRebase 충돌
커밋별로 충돌이 발생할 수 있습니다.
# Rebase conflict workflow
git checkout feature
git rebase main
# CONFLICT in commit C3: Merge conflict in src/app.ts
# 1. Resolve conflict in src/app.ts
git add src/app.ts
# 2. Continue rebase to next commit
git rebase --continue
# May hit another conflict in C4...
# CONFLICT in commit C4: Merge conflict in src/utils.ts
git add src/utils.ts
git rebase --continue
# Abort rebase if it gets too complex
git rebase --abort # returns to pre-rebase state
# Skip a problematic commit during rebase
git rebase --skip팀 워크플로우 전략
Merge 기반 워크플로우
가장 일반적인 팀 워크플로우.
# GitHub Flow (merge-based)
git checkout -b feature/add-auth
# ... make commits ...
git push -u origin feature/add-auth
# Open PR on GitHub
# Review + approve
# Click "Merge pull request" (creates merge commit)
# Or "Squash and merge" (single commit)Rebase 후 Merge 워크플로우
rebase로 업데이트 후 merge.
# Rebase-before-merge workflow
git checkout feature/add-auth
# ... make commits ...
# Before opening PR, update with latest main
git fetch origin
git rebase origin/main
# Force push (safe because it's your own branch)
git push --force-with-lease origin feature/add-auth
# Open PR on GitHub
# Merge with --no-ff to record integration point
git checkout main
git merge --no-ff feature/add-authSquash and Merge 워크플로우
모든 커밋을 하나로 합칩니다.
# Squash and merge (via GitHub UI or CLI)
git checkout main
git merge --squash feature/add-auth
git commit -m "feat: add authentication system"
# Before:
# main: A---B---C
# feature: A---B---D---E---F---G
# After squash-merge:
# main: A---B---C---H ← H contains all changes from D+E+F+G
# (feature branch can be deleted)Rebase의 황금 규칙
공유 원격 브랜치에 이미 푸시된 커밋을 rebase하지 마세요.
# DANGEROUS: Rebasing a shared branch
git checkout shared-feature
git rebase main
git push --force # !! This rewrites history for everyone!
# SAFE: Rebasing your own local branch
git checkout my-local-feature
git rebase main
# No push yet, or push --force-with-lease to your own branch
# SAFE: Using --force-with-lease instead of --force
git push --force-with-lease origin my-feature
# Fails if remote has commits you haven't seen모범 사례
Git Rebase vs Merge Best Practices:
1. Use merge for integrating feature branches into main
- Creates clear integration points
- Safe for shared branches
- Easy to revert entire features
2. Use rebase to keep feature branches up-to-date
- git rebase main (before opening PR)
- Creates clean, linear history
- Makes code review easier
3. Use interactive rebase to clean up before PR
- Squash fixup commits
- Reword unclear commit messages
- Drop debugging commits
4. Use git pull --rebase as default
- Avoids unnecessary merge commits
- git config --global pull.rebase true
5. Never rebase shared/pushed commits
- Only rebase your own unpushed work
- Use --force-with-lease, never --force
6. Use squash-merge for feature branches
- One clean commit per feature on main
- Detailed commits preserved in PR history
7. Use --no-ff for important merges
- Preserves the fact that a branch existed
- Makes git log --first-parent useful자주 묻는 질문
rebase와 merge 중 어느 것을 사용해야 하나요?
로컬 브랜치 업데이트에 rebase, 메인 브랜치 통합에 merge를 사용하세요.
rebase는 위험한가요?
공유 브랜치에서는 위험합니다. 로컬 미푸시 커밋에는 안전합니다.
squash and merge란?
모든 커밋을 하나로 합쳐서 머지합니다.
rebase를 취소할 수 있나요?
네. git reflog를 사용하세요.
팀은 rebase와 merge 중 어느 것을 사용해야 하나요?
하이브리드 접근이 최적입니다.
git pull --rebase란?
머지 커밋 대신 rebase로 업데이트를 가져옵니다.
관련 도구 및 가이드
- JSON Formatter - Format Git config files
- Diff Checker - Compare code changes before merge
- Git Commands Cheat Sheet
- Git Branch Naming Convention
- Git Cherry-Pick, Revert, and Reset Guide
- Git Workflow Strategies