개발이 취미인 사람

[Git] - Rebase vs Merge 차이점 본문

컴퓨터공학/Git

[Git] - Rebase vs Merge 차이점

RyanSin 2025. 12. 21. 20:00
반응형

개요

안녕하세요. 이번 시간에는 Git에서 브랜치를 통합하는 두 가지 방법인 Rebase와 Merge의 차이점에 대해 알아보겠습니다. 둘 다 브랜치를 합치는 작업이지만, 커밋 히스토리를 다루는 방식이 완전히 다릅니다. 혹시 이전 시간에 내용을 학습하고 오시지 못 하신 분들은 학습하고 오시는 걸 추천드리겠습니다.

 

[Git] - 브랜치 병합(Merge) 방법

- Rebase란?

Rebase는 말 그대로 "베이스를 다시 설정"하는 것입니다. 현재 브랜치의 커밋들을 다른 브랜치의 최신 커밋 위로 옮겨 놓습니다.

Merge vs Rebase 시각적 비교

초기 상태:

main:     A --- B --- C
                \
feature:         D --- E

Merge 사용 시:

main:     A --- B --- C ------- M (Merge Commit)
                \             /
feature:         D --- E ----

Rebase 사용 시:

main:     A --- B --- C
                      \
feature:               D' --- E' (커밋이 재생성됨)

Rebase 후 Fast-Forward Merge:

main:     A --- B --- C --- D' --- E'

- Rebase 기본 사용법

기본 명령어

# feature 브랜치에서 main을 기준으로 rebase
git switch feature
git rebase main

실습

# 1. 프로젝트 초기화
mkdir rebase-practice
cd rebase-practice
git init

# 2. main 브랜치 초기 커밋
echo "init" > file.txt
git add .
git commit -m "A: 초기 커밋"

# 3. feature 브랜치 생성 및 작업
git switch -c feature/login
echo "login" > login.txt
git add .
git commit -m "D: 로그인 추가"

echo "logout" >> login.txt
git add .
git commit -m "E: 로그아웃 추가"

# 4. main 브랜치에서 다른 작업 진행
git switch main
echo "update" >> file.txt
git add .
git commit -m "B: 파일 업데이트"

echo "more" >> file.txt
git add .
git commit -m "C: 추가 업데이트"

# 5. 현재 상태 확인
git log --oneline --all --graph
# * a1b2c3d (HEAD -> main) C: 추가 업데이트
# * b2c3d4e B: 파일 업데이트
# | * c3d4e5f (feature/login) E: 로그아웃 추가
# | * d4e5f6g D: 로그인 추가
# |/
# * e5f6g7h A: 초기 커밋

# 6. feature 브랜치에서 rebase 실행
git switch feature/login
git rebase main

# 출력
Successfully rebased and updated refs/heads/feature/login.

# 7. rebase 후 상태 확인
git log --oneline --all --graph
# * f6g7h8i (HEAD -> feature/login) E: 로그아웃 추가
# * g7h8i9j D: 로그인 추가
# * a1b2c3d (main) C: 추가 업데이트
# * b2c3d4e B: 파일 업데이트
# * e5f6g7h A: 초기 커밋

# 8. main에서 Fast-Forward Merge
git switch main
git merge feature/login

# 9. 최종 히스토리 (선형!)
git log --oneline
# f6g7h8i E: 로그아웃 추가
# g7h8i9j D: 로그인 추가
# a1b2c3d C: 추가 업데이트
# b2c3d4e B: 파일 업데이트
# e5f6g7h A: 초기 커밋

- Merge vs Rebase 상세 비교

항목 Merge Rebase

히스토리 분기 이력 보존 선형 히스토리
커밋 병합 커밋 생성 커밋 재생성 (해시 변경)
원본 보존 원본 커밋 유지 원본 커밋 변경
충돌 해결 한 번에 해결 커밋마다 해결 필요
협업 안전성 안전 주의 필요
사용 시점 공유 브랜치 로컬 브랜치

히스토리 비교

Merge 히스토리:

git log --oneline --graph
# *   h8i9j0k Merge branch 'feature/login'
# |\
# | * f6g7h8i E: 로그아웃 추가
# | * g7h8i9j D: 로그인 추가
# * | a1b2c3d C: 추가 업데이트
# * | b2c3d4e B: 파일 업데이트
# |/
# * e5f6g7h A: 초기 커밋

Rebase 히스토리:

git log --oneline --graph
# * f6g7h8i E: 로그아웃 추가
# * g7h8i9j D: 로그인 추가
# * a1b2c3d C: 추가 업데이트
# * b2c3d4e B: 파일 업데이트
# * e5f6g7h A: 초기 커밋

- Rebase의 황금률

⚠️ 절대 공유된 브랜치에서 Rebase하지 마세요!

왜 위험한가?

Rebase는 커밋의 해시값을 변경합니다. 이미 원격 저장소에 push한 커밋을 rebase하면:

# 팀원 A가 작업
git push origin feature  # 커밋 D, E 푸시

# 팀원 B가 같은 브랜치를 가져감
git pull origin feature  # 커밋 D, E 받음

# 팀원 A가 rebase 후 강제 푸시
git rebase main
git push --force origin feature  # D', E' 푸시 (해시 변경됨!)

# 팀원 B가 pull 시도
git pull origin feature
# 충돌 발생! D, E와 D', E'가 다른 커밋으로 인식됨

안전한 Rebase 사용 원칙

# ✅ 안전: 아직 push하지 않은 로컬 커밋
git rebase main

# ✅ 안전: 혼자 사용하는 브랜치
git rebase main
git push --force origin feature/my-branch

# ❌ 위험: 다른 사람과 공유 중인 브랜치
git rebase main  # 하지 마세요!

- Interactive Rebase

Interactive Rebase는 커밋 히스토리를 수정할 수 있는 강력한 기능입니다.

기본 사용법

# 최근 N개의 커밋을 수정
git rebase -i HEAD~N

# 특정 커밋 이후부터 수정
git rebase -i 커밋해시

실습

# 1. 여러 커밋 생성
echo "1" > num.txt && git add . && git commit -m "feat: 1 추가"
echo "2" >> num.txt && git add . && git commit -m "feat: 2 추가"
echo "3" >> num.txt && git add . && git commit -m "feat: 3 추가"
echo "4" >> num.txt && git add . && git commit -m "feat: 4 추가"

# 2. Interactive Rebase 실행
git rebase -i HEAD~4

# 에디터가 열림:
# pick a1b2c3d feat: 1 추가
# pick b2c3d4e feat: 2 추가
# pick c3d4e5f feat: 3 추가
# pick d4e5f6g feat: 4 추가

Interactive Rebase 명령어

명령어 축약 설명

pick p 커밋 그대로 사용
reword r 커밋 메시지 수정
edit e 커밋 수정 (파일 변경 가능)
squash s 이전 커밋과 합침 (메시지 합침)
fixup f 이전 커밋과 합침 (메시지 버림)
drop d 커밋 삭제

커밋 합치기 (Squash)

git rebase -i HEAD~4

# 에디터에서 수정:
# pick a1b2c3d feat: 1 추가
# squash b2c3d4e feat: 2 추가
# squash c3d4e5f feat: 3 추가
# squash d4e5f6g feat: 4 추가

# 저장 후 커밋 메시지 편집 화면이 나옴
# feat: 1~4 추가

커밋 순서 변경

git rebase -i HEAD~4

# 에디터에서 순서 변경:
# pick d4e5f6g feat: 4 추가
# pick a1b2c3d feat: 1 추가
# pick c3d4e5f feat: 3 추가
# pick b2c3d4e feat: 2 추가

커밋 메시지 수정

git rebase -i HEAD~3

# 에디터에서 수정:
# reword a1b2c3d feat: 1 추가
# pick b2c3d4e feat: 2 추가
# pick c3d4e5f feat: 3 추가

# 저장 후 새 커밋 메시지 입력 화면이 나옴

- Rebase 충돌 해결

Rebase 중 충돌이 발생하면 각 커밋마다 해결해야 합니다.

# 1. Rebase 시작
git rebase main

# 충돌 발생 시:
# CONFLICT (content): Merge conflict in file.txt
# error: could not apply a1b2c3d... feat: 기능 추가

# 2. 충돌 파일 확인 및 수정
git status
# 충돌 파일 수정...

# 3. 수정 완료 후 스테이징
git add file.txt

# 4. Rebase 계속 진행
git rebase --continue

# 5. 또 다른 충돌 시 2-4 반복

# 전체 Rebase 취소
git rebase --abort

# 현재 커밋 건너뛰기
git rebase --skip

- 실전 사용 시나리오

시나리오 1: PR 전 커밋 정리

# feature 브랜치에서 작업 완료
git switch feature/user-profile

# 여러 WIP 커밋을 하나로 정리
git rebase -i main

# 에디터에서:
# pick a1b2c3d feat: 프로필 페이지 추가
# fixup b2c3d4e WIP
# fixup c3d4e5f WIP: 스타일 수정
# fixup d4e5f6g fix: 오타 수정

# main 최신화 후 rebase
git rebase main

# PR 생성

시나리오 2: main 브랜치 변경사항 가져오기

# Merge 방식
git switch feature/login
git merge main  # 병합 커밋 생성

# Rebase 방식 (선형 히스토리 유지)
git switch feature/login
git rebase main  # 커밋을 main 위로 이동

시나리오 3: 잘못된 커밋 수정

# 3번째 전 커밋의 오타 수정
git rebase -i HEAD~3

# edit으로 변경
# edit a1b2c3d feat: 기능 추가 (오타 있음)
# pick b2c3d4e feat: 다른 기능
# pick c3d4e5f feat: 또 다른 기능

# 파일 수정
# ... 오타 수정 ...
git add .
git commit --amend
git rebase --continue

- 언제 Merge? 언제 Rebase?

Merge를 사용해야 할 때

# ✅ 공유 브랜치 (main, develop)에 병합할 때
git switch main
git merge feature/login

# ✅ 팀원과 함께 사용하는 브랜치
git merge shared-branch

# ✅ 브랜치 이력을 보존하고 싶을 때
git merge --no-ff feature/login

Rebase를 사용해야 할 때

# ✅ 로컬에서 작업 중인 브랜치 정리
git rebase main

# ✅ PR 전 커밋 히스토리 정리
git rebase -i HEAD~5

# ✅ 선형 히스토리를 유지하고 싶을 때
git rebase main
git switch main
git merge feature/login  # Fast-Forward

- 명령어 정리

# 기본 Rebase
git rebase 대상브랜치

# Interactive Rebase
git rebase -i HEAD~N
git rebase -i 커밋해시

# Rebase 중 제어
git rebase --continue    # 계속 진행
git rebase --abort       # 전체 취소
git rebase --skip        # 현재 커밋 건너뛰기

# Rebase 후 강제 푸시 (주의!)
git push --force origin 브랜치명
git push --force-with-lease origin 브랜치명  # 더 안전

마무리

이번 시간에는 Rebase와 Merge의 차이점에 대해 알아봤습니다. 두 방법 모두 장단점이 있으며, 상황에 맞게 선택하면 됩니다. 핵심은 **"공유된 브랜치에서는 Rebase 금지"**입니다. Interactive Rebase는 커밋 히스토리를 깔끔하게 정리할 수 있는 강력한 도구이니 꼭 연습해보시길 추천드립니다.

다음 시간에는 충돌(Conflict) 해결 방법에 대해 알아보겠습니다.


참고 자료