[GitHub 100일 챌린지] Day 49 - Rebase 이해하기
[GitHub 100일 챌린지] Day 49 - Rebase 이해하기
100일 챌린지 Day 49 - Git Rebase로 깔끔한 커밋 히스토리를 만드는 방법을 배웁니다.
배울 내용
- Rebase란
- Rebase 실습
- Merge vs Rebase
Topic1. Rebase란
커밋 히스토리를 재작성하여 선형으로 만드는 방법입니다.
Rebase의 개념
Merge와의 차이:
gitGraph
commit id: "C1"
commit id: "C2"
branch feature
checkout feature
commit id: "C3"
checkout main
commit id: "C4"
Merge 결과:
gitGraph
commit id: "C1"
commit id: "C2"
branch feature
checkout feature
commit id: "C3"
checkout main
commit id: "C4"
merge feature tag: "M (Merge Commit)"
Rebase 결과:
gitGraph
commit id: "C1"
commit id: "C2"
commit id: "C4 (main)"
commit id: "C3' (feature rebased)"
히스토리 비교:
1
2
3
4
5
6
7
8
9
10
11
Merge:
C1 ← C2 ← C4 ← M
↑ ↗
└─ C3 ──┘
→ 병합 커밋 M 생성
→ 히스토리 분기됨
Rebase:
C1 ← C2 ← C4 ← C3'
→ C3를 C4 뒤로 이동
→ 선형 히스토리
Rebase의 원리
Rebase가 하는 일:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 상황: feature 브랜치를 main에 rebase
git checkout feature
git rebase main
# Git의 내부 동작:
1. feature의 커밋들을 임시 저장 (C3)
2. feature를 main의 최신 커밋으로 이동 (C4)
3. 저장한 커밋들을 하나씩 재적용 (C3')
# 결과:
C1 ← C2 ← C4 ← C3'
↑
feature
커밋이 재작성되는 과정:
1
2
3
4
5
6
7
8
9
10
11
원본 커밋 C3:
- 부모: C2
- 변경사항: add feature.js
- SHA: abc123
Rebase 후 C3':
- 부모: C4 (변경!)
- 변경사항: add feature.js (동일)
- SHA: def456 (변경!)
⚠️ SHA가 달라짐 = 새로운 커밋!
해보기: Rebase 상황 만들기
시나리오: main이 앞서 나간 상황
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 프로젝트 초기화
mkdir rebase-demo
cd rebase-demo
git init
# 초기 커밋
echo "v1.0" > VERSION
git add VERSION
git commit -m "C1: Initial version"
echo "# App" > README.md
git add README.md
git commit -m "C2: Add README"
# feature 브랜치 생성
git checkout -b feature/new-ui
# feature에서 작업
echo "UI code" > ui.js
git add ui.js
git commit -m "C3: Add new UI"
# main으로 돌아가서 작업 (main이 앞서감)
git checkout main
echo "v1.1" > VERSION
git add VERSION
git commit -m "C4: Bump version to 1.1"
# 히스토리 확인
git log --oneline --all --graph
# 출력:
* C4 (HEAD -> main) Bump version to 1.1
| * C3 (feature/new-ui) Add new UI
|/
* C2 Add README
* C1 Initial version
# feature가 main보다 뒤처짐!
결과
Rebase가 필요한 상황:
1
2
3
✅ feature 브랜치가 main보다 뒤처짐
✅ main의 최신 변경사항 필요
✅ 깔끔한 선형 히스토리 원함
언제 사용하나?:
1
2
3
4
5
6
7
8
9
10
개인 브랜치:
✅ 아직 push 안 함
✅ 나만 사용하는 브랜치
→ Rebase 사용 OK!
공유 브랜치:
❌ 이미 push 함
❌ 다른 사람이 사용 중
→ Rebase 사용 위험!
→ Merge 사용 권장
Topic2. Rebase 실습
실제로 Rebase를 수행해봅니다.
기본 Rebase
Rebase 명령어:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# feature 브랜치로 전환
git checkout feature/new-ui
# main을 기준으로 rebase
git rebase main
# 출력:
Successfully rebased and updated refs/heads/feature/new-ui.
# 히스토리 확인
git log --oneline --graph
# 출력:
* C3' (HEAD -> feature/new-ui) Add new UI
* C4 (main) Bump version to 1.1
* C2 Add README
* C1 Initial version
# 선형 히스토리!
변경사항 확인:
1
2
3
4
5
6
7
8
# Rebase 전 C3의 SHA
# abc123def
# Rebase 후 C3'의 SHA
git log --oneline -1
# def456abc
# SHA가 바뀜 = 새로운 커밋!
Interactive Rebase
커밋을 수정하며 Rebase:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 대화형 rebase
git rebase -i main
# 에디터가 열림:
pick C3 Add new UI
pick C5 Fix typo
pick C6 Update docs
# Commands:
# p, pick = 커밋 사용
# r, reword = 커밋 메시지 수정
# e, edit = 커밋 수정
# s, squash = 이전 커밋과 합치기
# f, fixup = squash와 동일, 메시지 버림
# d, drop = 커밋 삭제
커밋 합치기 (Squash):
1
2
3
4
5
6
7
8
9
10
# 여러 작은 커밋을 하나로
git rebase -i main
# 에디터에서:
pick C3 Add new UI
squash C5 Fix typo
squash C6 Update docs
# 저장하면 C3, C5, C6이 하나로 합쳐짐
# 새 커밋 메시지 작성 가능
해보기: 실전 Rebase 워크플로우
시나리오: PR 전 깔끔하게 정리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# === 초기 설정 ===
mkdir pr-rebase
cd pr-rebase
git init
echo "# Project" > README.md
git add README.md
git commit -m "Initial commit"
# main에 새 변경사항
git checkout -b feature/login
# === feature에서 지저분하게 작업 ===
echo "login form" > login.html
git add login.html
git commit -m "WIP: start login"
echo "add validation" >> login.html
git add login.html
git commit -m "add validation"
echo "fix typo" >> login.html
git add login.html
git commit -m "fix typo"
echo "add style" >> login.css
git add login.css
git commit -m "add css"
# === main에 핫픽스 ===
git checkout main
echo "v1.0.1" > VERSION
git add VERSION
git commit -m "hotfix: Bump version"
# === 히스토리 확인 ===
git checkout feature/login
git log --oneline --graph
# 출력:
* L4 add css
* L3 fix typo
* L2 add validation
* L1 WIP: start login
* I1 Initial commit
# 지저분한 히스토리!
# === Interactive Rebase로 정리 ===
git rebase -i main
# 에디터:
pick L1 WIP: start login
squash L2 add validation
squash L3 fix typo
pick L4 add css
# 저장 후 커밋 메시지 작성:
feat: Add login form with validation
- Implement login HTML form
- Add client-side validation
- Include CSS styling
# === 결과 확인 ===
git log --oneline --graph
# 출력:
* N2 (HEAD -> feature/login) add css
* N1 feat: Add login form with validation
* H1 (main) hotfix: Bump version
* I1 Initial commit
# 깔끔한 히스토리!
Rebase 충돌 해결
충돌 발생 시:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
git rebase main
# 출력:
CONFLICT (content): Merge conflict in login.html
error: could not apply L1... Add login form
hint: Resolve all conflicts manually
hint: After resolving, mark with "git add/rm <conflicted_files>"
hint: then run "git rebase --continue"
# 충돌 해결
vim login.html
# (Conflict Marker 제거)
git add login.html
# Rebase 계속
git rebase --continue
# 또는 취소
git rebase --abort
결과
Rebase 장점:
1
2
3
4
✅ 선형 히스토리 (읽기 쉬움)
✅ 깔끔한 커밋 로그
✅ PR 리뷰 쉬워짐
✅ Bisect 사용 용이
Rebase 주의사항:
1
2
3
4
⚠️ 커밋 SHA 변경됨
⚠️ 히스토리 재작성
⚠️ Push한 커밋은 rebase 금지
⚠️ 공유 브랜치는 위험
Topic3. Merge vs Rebase
두 방식의 차이와 선택 기준입니다.
Merge의 특징
Merge 동작:
1
2
3
4
5
6
7
git checkout main
git merge feature
# 결과:
C1 ← C2 ← C4 ← M
↑ ↗
└─ C3 ──┘
Merge 장점:
1
2
3
4
5
✅ 히스토리 보존
✅ 작업 흐름 명확
✅ 안전함 (히스토리 변경 없음)
✅ 브랜치 작업 추적 가능
✅ 충돌 한 번만 해결
Merge 단점:
1
2
3
4
❌ 히스토리 복잡해짐
❌ 병합 커밋 많아짐
❌ 그래프 지저분
❌ Bisect 사용 어려움
Rebase의 특징
Rebase 동작:
1
2
3
4
5
git checkout feature
git rebase main
# 결과:
C1 ← C2 ← C4 ← C3'
Rebase 장점:
1
2
3
4
5
✅ 선형 히스토리
✅ 깔끔한 로그
✅ 읽기 쉬움
✅ Bisect 사용 쉬움
✅ PR 리뷰 편함
Rebase 단점:
1
2
3
4
5
❌ 히스토리 재작성
❌ 위험함 (잘못 사용 시)
❌ 충돌 여러 번 해결 가능
❌ Push 강제 필요 (force push)
❌ 공유 브랜치 위험
선택 기준
Merge를 사용하는 경우:
1
2
3
4
5
6
7
8
9
✅ 공유 브랜치 (main, develop)
✅ 공개 브랜치 (이미 push됨)
✅ 히스토리 보존 중요
✅ 팀 협업 브랜치
✅ 릴리스 브랜치
예시:
git checkout main
git merge feature/login --no-ff
Rebase를 사용하는 경우:
1
2
3
4
5
6
7
8
9
✅ 개인 브랜치 (아직 push 안함)
✅ 로컬 작업만
✅ PR 전 정리
✅ 깔끔한 히스토리 원함
✅ 작은 feature 브랜치
예시:
git checkout feature/my-work
git rebase main
해보기: 워크플로우 비교
Merge 워크플로우:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Feature 개발
git checkout -b feature/payment
# ... 작업 ...
git commit -m "Add payment"
# main에 병합
git checkout main
git merge feature/payment
# 히스토리:
* M (main) Merge branch 'feature/payment'
|\
| * P (feature/payment) Add payment
* | H Hotfix
|/
* I Initial
# 브랜치 작업 명확히 보임
Rebase 워크플로우:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Feature 개발
git checkout -b feature/payment
# ... 작업 ...
git commit -m "Add payment"
# main 최신화 후 rebase
git checkout main
git pull
git checkout feature/payment
git rebase main
# main에 Fast-Forward 병합
git checkout main
git merge feature/payment
# 히스토리:
* P (HEAD -> main, feature/payment) Add payment
* H Hotfix
* I Initial
# 선형 히스토리
Golden Rule
절대 규칙:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
❌ 절대 금지:
push한 공개 브랜치를 rebase하지 마세요!
git checkout main
git rebase feature # ❌ 위험!
이유:
- 다른 사람이 사용 중일 수 있음
- SHA가 바뀌면 협업 깨짐
- Force push 필요
- 충돌과 혼란 발생
✅ 안전한 사용:
git checkout feature # 개인 브랜치
git rebase main # ✅ 안전!
팀 규칙 예시
실무 가이드라인:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1. Main/Develop 브랜치
→ Merge만 사용
→ --no-ff 옵션 권장
→ 히스토리 보존
2. Feature 브랜치
→ PR 전: Rebase 사용 (정리)
→ PR 병합: Squash Merge
3. 개인 작업 브랜치
→ Rebase 자유롭게 사용
→ Push 전에만 사용
4. Hotfix 브랜치
→ Merge 사용
→ 빠른 병합 우선
결과
Merge vs Rebase 요약:
1
2
3
4
5
6
7
8
9
10
11
12
Merge:
- 안전하고 보수적
- 히스토리 보존
- 공유 브랜치에 적합
Rebase:
- 깔끔하고 공격적
- 히스토리 재작성
- 개인 브랜치에 적합
황금률:
"공개/공유 브랜치는 절대 rebase 금지!"
정리
오늘 배운 내용:
1. Rebase 개념:
- 커밋을 다른 base로 이동
- 선형 히스토리 생성
- 커밋 SHA 변경됨
2. Rebase 사용법:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 기본 rebase
git checkout feature
git rebase main
# Interactive rebase
git rebase -i main
# 충돌 해결
git add <file>
git rebase --continue
# 취소
git rebase --abort
3. Merge vs Rebase:
1
2
3
4
Merge: 안전, 히스토리 보존, 공유 브랜치
Rebase: 깔끔, 히스토리 재작성, 개인 브랜치
황금률: 공개 브랜치 rebase 금지!
4. 실무 사용:
- PR 전: Interactive rebase로 정리
- 개인 브랜치: 자유롭게 rebase
- 공유 브랜치: Merge만 사용
다음 단계: Day 50에서 Git Flow를 배웁니다.
완료 체크:
- Rebase의 개념을 이해했다
- Rebase를 수행할 수 있다
- Merge와 Rebase의 차이를 안다
- 언제 Rebase를 사용할지 안다
- Rebase의 위험성을 이해했다
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
