말 그대로, base를 다시 설정한다는 뜻이다. git에서 base는 나의 branch를 딴 시점의 master base를 의미한다. master branch의 가장 최신 base는 HEAD
라고 한다.
rebase를 하면 fastforward merge 가 이루어지는데, 새로 commit한 내용이 base에 이어서, 바로 순차적으로 merge 되는 경우를 말한다.
rebase를 하지 않는 경우, merge 시점에서 이미 HEAD
가 바뀌었을 때, 해당 base보다 미래에 생성된 HEAD
를 포함하는 merge가 이루어지고, 자신의 branch의 commit 내용을 merge 하기 위해 merge commit
이 자동으로 생성 된다 (즉, non fastforward merge라고 보면 된다.)
이는 여러명이서 협업을 할 시, 내용의 이력이 모두 그대로 남아 있기 때문에 이력이 복잡해지는 단점이 있다. 이 같은 단점으로 인하여, rebase를 사용하여, 새로운 HEAD
로 base를 다시 잡아준다.
rebase를 사용하면, merge commit이 생성되지 않고, 최신 HEAD
뒤에 순차적으로 commit 내용이 merge 된다.
rebase의 단점은 commit이 merge 되지 않고, 하나하나 씩 올라간다는 점이다. 따라서, 각각의 commit의 conflict을 수정하여 해결 해 주어야 한다.(일주일전 코드를 다시 수정하는 경우도 있다.)
반면 merge commit의 장점은 내역은 지저분하나, conflict 해결 시, 전체적인 큰 그림을 보고 한번에 수정, 해결이 가능하다.
Rebase의 경우에도 여러개의 commits을 하나의 commit 으로 합치는 것이 가능하다. 이를 squash
라고 한다. 이미 pull request를 한 경우, 이전의 내역을 지우고 다시 새로운 하나의 commit으로 만들어 줄 때 사용할 수 있다. $ git rebase -i
명령어를 사용하여, rebase 과정에 직접 참여할 수 있다. 어떤 commit을 pick
하고, 어떤 commit을 squash
할지를 지정할 수 있다.
일련의 과정이 끝난 후,다시 push하기 위해서는 force
명령어를 사용하여 push를 진행 하여야 한다. commit의 history를 바꾸는 일은 중앙 저장소 입장에서 보았을 때, 또 다른 branch가 갈라졌다고 인식하기 때문이다. --f
를 하지 않은 경우, github은 다시 pull을 하고 merge를 하라고 제안한다. force push 는 내가 올리는 history를 그대로 받으라고 github에게 명령하는 것과 같다.
주의점
force push는 나.의.브.랜.치 에서만 진행하자. master에서 진행하는 경우, 다른 사람들의 commit history 바꾸어 버리게 되기 때문이다. 실제 많은 기업에서는 이를 방지하기 위해, master force push를 막아 놓기도 한다.
Case: 이미 PR을 날린 상태에서 충돌이 확인되어, 충돌을 확인한 후 rebase&squash하여 commit해야 되는 상황.
$ git checkout master
$ git pull origin master
$ git checkout <local branch name>
$ git rebase -i master
# 충돌 해결하라는 에러 메세지가 표시된다
# 파일 수정 및 충돌 해결
$ git add . # commit은 하지 않음
$ git rebase --continue
# interactive 화면에서 pick and squash, commit message 작성 실행
$ git push origin <local branch name> -f