pull request(PR)
을 할 때 merge 옵션이 있다
여기서 옵션들은 merge의 옵션들과 같다
Create a merge commit -> git merge <branch> --no-ff
Squash and merge -> git merge <branch> --squash
Rebase and merge -> git rebase <branch>
세가지를 비교를 비교해보기 위해 상황이 다음과 같다고 가정하자
위와 같은 상황에서 긴급한 버그 수정을 위해 Hotfix
가 Master
로부터 분기하여 작업을 두개(Commit 2개) 진행했다고 가정
master > git log
* 03c0e57 (Hotfix) fix bugB
* 1693ca1 fix bugA
* a7ee0c1 (HEAD -> master, origin/master) base commit
1. git merge –no-ff, –ff
git merge --no-ff
를 알기 위해선 --ff
를 알아야한다
-ff
는 fast-forward 의 줄임말로써 빨리감기라는 뜻이다
git merge --ff
를 할 경우
master > git merge Hotfix --ff
Updating a7ee0c1..03c0e57
Fast-forward
master > git log
* 03c0e57 (HEAD -> master, Hotfix) fix bugB
* 1693ca1 fix bugA
* a7ee0c1 (origin/master) base commit
Master
의 log에는 Hotfix
의 커밋들만 추가되고 따로 추가되는 commit은 없다
-ff
는 git merge
의 기본 옵션이기때문에 git merge
와 git merge --ff
는 같은 뜻이다
초기화
다른 옵션도 테스트하기 위해 git reset --hard <돌아가려는 workspace>
master > git reset --hard origin/master
HEAD is now at a7ee0c1 base commit
master > git log
* 272c460 (Hotfix) fix bugB
* 252a393 fix bugA
* 498325c testC.txt
* a7ee0c1 (HEAD -> master, origin/master) base commit
git merge --no-ff
를 할 경우
master
에 변경이력이 없어도 fast-farward
를 하지 않고 no-fast-farward
를 한다
no-fast-farward
: master
의 log에는 Hotfix의 작업내역 commit 2개와 병합commit(Merge ~ from
)이 기록
master > git merge Hotfix --no-ff // merge내용 작성
Merge made by the 'recursive' strategy.
master > git log
* 842db67 (HEAD -> master) Merge branch 'Hotfix'
|\
| * 03c0e57 (Hotfix) fix bugB
| * 1693ca1 fix bugA
|/
* a7ee0c1 (origin/master) base commit
이 때, 만들어진 commit(Merge branch 'Hotfix'
)는 2개의 Parent(Hotfix
, master
)를 갖는다
--ff
를 적용이 안되고 --no-ff
로 적용되는 경우
하지만 --ff
로 옵션을 주어도 --no-ff
로 적용이 되는 경우가 있다
hotfix
가 작업을 하는동안master
에 변경 내역이 있는 경우
master 작업 추가
master > vi testC.txt
master !1 > git add .
master +1 > git commit -m "testC.txt"
master > git log
* | 00c9de9 (HEAD -> master) testC.txt
| * 03c0e57 (Hotfix) fix bugB
| * 1693ca1 fix bugA
|/
* a7ee0c1 (origin/master) base commit
merge
master > git merge Hotfix --ff
// Merge branch 'Hotfix'
master > git log
* 1925dd0 (HEAD -> master) Merge branch 'Hotfix'
|\
* | 00c9de9 testC.txt
| * 03c0e57 (Hotfix) fix bugB
| * 1693ca1 fix bugA
|/
* a7ee0c1 (origin/master) base commit
--no-ff
로 적용이 된다
2. git merge –squash
squash란 영단어 뜻 그대로 뭉개다 라는 뜻이다
master
에 Hotfix
의 commit들이 반영되지않고 새 commit만 반영된다
master > git merge --squash Hotfix
Updating a7ee0c1..03c0e57
Fast-forward
Squash commit -- not updating HEAD
testA.txt | 2 +-
testB.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
// squash는 commit이 생성되지않고 Staged상태만 된다
// commit 추가
master +2 > git add .
master +2 > git commit -m "fix bugA,B"
[master 48975f6] fix bugA,B
2 files changed, 2 insertions(+), 2 deletions(-)
master > git log
* 48975f6 (HEAD -> master) fix bugA,B
| * 03c0e57 (Hotfix) fix bugB
| * 1693ca1 fix bugA
|/
* a7ee0c1 (origin/master) base commit
이 떄, fix bugA,B
의 parent는 한개(master
)이다
3. git rebase
rebase
란 모든 commit이 합쳐지지 않고 각각 master에 추가된다
rebase
의 기능을 알기 위해서 master
를 base commit
으로 reset
한뒤 작업변경을 하고 testC.txt
commit을 추가한다
master > git reset --hard origin/master
HEAD is now at a7ee0c1 base commit
master > vi testC.txt
master !1 > git add .
master +1 > git commit -m "testC.txt"
[master 498325c] testC.txt
1 file changed, 1 insertion(+), 1 deletion(-)
master > git log
498325c (HEAD -> master) testC.txt
| * 03c0e57 (Hotfix) fix bugB
| * 1693ca1 fix bugA
|/
* a7ee0c1 (origin/master) base commit
rebase 작업 진행
master > git checkout Hotfix
Switched to branch 'Hotfix'
Hotfix > git rebase master
First, rewinding head to replay your work on top of it...
Applying: fix bugA
Applying: fix bugB
Hotfix > git checkout master
Switched to branch 'master'
master > git merge Hotfix
Updating 498325c..272c460
Fast-forward
testA.txt | 2 +-
testB.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
master > git log
* 272c460 (HEAD -> master, Hotfix) fix bugB
* 252a393 fix bugA
* 498325c testC.txt
* a7ee0c1 (origin/master) base commit
fix bugA
, fix bugB
는 Hotfix
에서 작업한 commit의 내용이지만 commit의 id를 보면 다른 것을 확인 할 수 있다
4. 무엇을 선택해야하는가
rebase
의 경우 자칫 잘못하면 엉켜버릴수가 있다.sqaush
:master
에Hotfix
이 commit 2개(commit A
,commit B
)를 PR요청하고squash
로 merge했다고 가정- merge 이후에,
Hotfix
가 추가작업(commit C
,commit D
)을 하고 또 PR을 보내면 4개의 커밋(commit A
,commit B
,commit C
,commit D
)이 PR내역에 포함되어 보내진다. 과거에 했던 commit (commit A
,commit B
)이 포함되는 문제가 있다
- merge 이후에,
merge
: 그냥merge
를 사용할 경우sqaush
의 위 문제점이 발생하지않고 작업했던 내역들만 PR 요청을 할 수 있다. 하지만Hotfix
의 commit(commit C
,commit D
)들이 전부master
의 log의 올라간다.- 반면에
-squash
는 한개의 commit(위 예제경우fix bugA,B
)만master
에 올라간다.commit A
,commit B
는 PR 내역을 들어가면 볼 수있다.
- 반면에
결론
- 일회성 branch의 경우 :
squash
- 지속적인 branch의 경우 :
merge --no-ff
- ex) git flow 모델에서
develop
- ex) git flow 모델에서
댓글 쓰기