Git Rebase

2019.07.20

@godori

sat10am Git Study

브랜치를 합치는 방법

Merge

Rebase

Merge

Merge

두 브랜치의 마지막 커밋 두 개(C3, C4)와 공통 조상(C2)을 사용하는 3-way Merge로 새로운 커밋을 만들어 낸다

전략:

C4         C3

C2

C5

Merge

3-way-merge

1. 내 브랜치 커밋

2. 남의 브랜치 커밋

3. base가 되는 공통 조상 커밋

다음 세 개의 변화를 비교합니다.

3-way-merge

My Base Other
a
b
c
d

3-way-merge

My Base Other
a a a'
b b b
c' c c''
d' d d

3-way-merge

My Base Other
a a a'
b b b
c' c c''
d' d d
Merge
a'
b
conflict
d'

2-way-merge case

Other
a'
b
c''
d'
Merge
?
b
?
?
My
a
b
c'
d

그래서 git은 3-way-merge를 씁니다.

Rebase

Rebase

C3 에서 변경된 사항을 Patch로 만들고 이를 다시 C4 에 적용시킨다.

전략:

diff 내용이 담긴 파일

$ git checkout feature
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: f1
Applying: f2
$ git merge feature

Rebase

feature

master

base

m1

m2

f1

f2

b

a

하려는 것: feature의 base를 b가 아니라 m2로 바꾸고 싶다

Rebase

feature

master

base

m1

m2

f1

f2

b

a

feature

master

base

m1

m2

f1

f2

b

a

f1

f2

master

base

m2

f1

f2

b

a

m1

feature를 master에 rebase 한다

=

feature의 master에 대한 공통 조상인 base를 master로 변경한다

feature

head

master

base

m2

f1

f2

b

a

m1

▵1

▵2

feature

head

Step 1

base에서 현재 브랜치(feature)까지의 변경 사항을 구한다

diff patch: ▵1, ▵2

master

base

m2

f1

f2

b

a

m1

feature

head

Step 2

head를 master로 변경한다

diff patch: ▵1, ▵2

master

base

m2

f1

f2

b

a

m1

feature

head

Step 3

변경사항 ▵1을 적용하여 새로운 커밋 f1' 생성

diff patch: ▵1, ▵2

f1'

▵1

master

base

m2

f1

f2

b

a

m1

feature

head

Step 4

변경사항 ▵2를 적용하여 새로운 커밋 f1' 생성

diff patch: ▵1, ▵2

f1'

▵1

f2'

▵2

master

base

m2

f1

f2

b

a

m1

feature

head

Step 5

feature가 f2'를 가리키도록 한다

이때 f1과 f2는 저장소 내에는 존재하지만, 찾아갈 포인터가 없는 dangling 상태가 된다.

f1'

f2'

(dangling)

dangling 된 커밋은 가비지 컬릭션 대상이 된다.

git gc 참조

master

base

m2

b

a

m1

feature

Step 6

feature를 master로 fast-forward merge하여 완료

f1'

f2'

head

Rebase

master

base

m1

m2

f1

f2

b

a

feature

feature로 체크아웃 한다

Rebase

2. Master의 워킹 카피에 f2를 병합한다 (Applying f2)

master

base

f1'

m2

f1

f2

b

a

m1

f2'

1. Master의 워킹 카피에 f1을 병합한다(Applying f1)

master

base

f1'

m2

f1

f2

b

a

m1

feature

3. Master로 체크아웃하고 병합하여 마무리(fast-forward)

master

base

f1'

m2

b

a

m1

f2'

feature

Rebase 활용

Server는 테스트가 덜 된 상태

Client만 master에 합치고 싶다

이때 server와 상관없는 커밋은 c8, c9

git rebase --onto master server client

onto 옵션을 사용

client에서만 변경된 브랜치를 적용하고 싶을 때 유용하다

server와 client의 공통 조상을 찾음

client의 변경 부분만 master에 적용

$ git checkout master
$ git merge client

이제 다시 마스터로 돌아가서 fast-foward merge

Rebase의 위험성

리모트에 Push한 커밋을 Rebase 하면 안 됨

Rebase는 기존의 커밋을 그대로 사용하는 것이 아니라 내용은 같지만 다른 커밋을 새로 만들기 때문

내가 올린 커밋을 동료가 체크아웃 받아 작성하는데

그 커밋을 리베이스 해버리면

동료는 없는 커밋으로 작업한 꼴

Rebase vs Merge

히스토리를 보는 관점의 차이

 💬

프로젝트가 어떻게 진행되었나에 대한 이야기

📜

작업한 내용의

사실 기록

역사가 어떻게 변경될 수 있어!

 

커밋 히스토리 변경은 거짓말을 하는 것

지저분한 Merge 기록을 남겨야 할까?


다른 사람에게 다듬어서 보여주자

로컬에서는 히스토리를 정리를 위해

Rebase 할 수도 있음

BUT

리모트에 Push한 커밋은

절대로 Rebase 하면 안됨!

프로젝트나 팀 상황에 따라 다르지만, 일반적인 원칙은

Thank you!

git-rebase

By Eunjeong Ko

git-rebase

  • 276