본문으로 건너뛰기
Git Rebase complete guide cover

# 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)**을 생성하여 두 브랜치의 히스토리를 합칩니다. 원본 커밋은 그대로 유지됩니다.

핵심 차이점 정리

특성RebaseMerge
히스토리선형(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 loggit 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
# ...

충돌 최소화 전략

  1. 자주 rebase하기: 변경이 적을 때 자주 하면 충돌도 적습니다.
  2. 작은 커밋 단위: 큰 커밋보다 작은 커밋이 충돌 해결이 쉽습니다.
  3. 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의 핵심 포인트:

  1. Rebase는 커밋을 새로 만듭니다. 원본 커밋의 해시가 변경됩니다.
  2. 푸시한 커밋은 rebase하지 마세요. 팀원에게 혼란을 줍니다.
  3. Interactive Rebase로 커밋을 정리하세요. squash, fixup으로 의미 있는 단위로 만듭니다.
  4. --force-with-lease를 사용하세요. --force보다 안전합니다.
  5. reflog는 당신의 친구입니다. 실수해도 거의 항상 복구할 수 있습니다.
  6. 팀 규칙을 정하세요. Rebase와 Merge를 언제 사용할지 합의합니다.

Rebase는 처음엔 두렵지만, 이해하고 나면 Git을 훨씬 효과적으로 사용할 수 있습니다. 개인 브랜치에서 충분히 연습한 후, 팀 워크플로우에 적용해보세요. 깔끔한 히스토리의 가치를 체감하게 될 것입니다.

이 글 공유하기:
My avatar

글을 마치며

이 글이 도움이 되었기를 바랍니다. 궁금한 점이나 의견이 있다면 댓글로 남겨주세요.

더 많은 기술 인사이트와 개발 경험을 공유하고 있으니, 다른 포스트도 확인해보세요.

유럽살며 여행하며 코딩하는 노마드의 여정을 함께 나누며, 함께 성장하는 개발자 커뮤니티를 만들어가요! 🚀


관련 포스트