git rebase 하는 방법
rebase 한 번도 안써서 방법을 모르는 분들을 위한 글
처음 코딩을 배우면서 프로젝트를 할 때는 git merge만 사용했다. 개발자로서 처음으로 다른 개발자와 협업을 하면서 깔끔하게 commit을 관리할 수 있는 rebase 방법을 익히게 되었다. 나처럼 한 번도 git rebase를 써본 적 없는 분들을 위해 내가 지금 쓰고 있는 방법을 풀어써보려고 한다!
git merge와 rebase의 차이를 알고 싶다면 Outsider님의 블로그글을 추천한다.
👉 git merge와 rebase 비교하기 : https://blog.outsider.ne.kr/666
master에 다른 branch를 병합할 때 쓰이는 방법이 두 가지인데, 하나는 merge이고, 다른 하나는 rebase이다.
merge와 rebase를 했을 때 가장 큰 차이는 “깔끔함”
만약 feature/test라는 branch를 만들어서 열심히 작업을 하고 master에 merge를 사용해서 병합한다고하면, feature/test에서 기록한 모든 commit이 master의 commit으로 기록된다.
rebase 방식을 사용해서 병합한다면, 내 작업하면서 남겼던 commit 중 불필요한 것들은 생략시키고 필요한 commit만 남겨서 master에 병합하기 때문에 master의 commit은 항상 깔끔하게 관리된다는 장점이 있다.
똑같은 병합이지만, 나중에 master의 commit을 볼 때 깔끔하게 볼 수 있어서 여러 명이 협업할 때 유용하다.
(참고: WIP는 work in progress 의 약자로 작업중이라는 뜻이다. 커밋은 남겨야겠고, 딱히 쓸 말은 없을 때 자주 써먹고 있다.)
내가 하고 있는 git rebase 방법
- master에서 feature/test라는 branch를 만들고 퇴근 전까지 열심히 작업했다 가정해보자. 퇴근 전에 commit을 남긴다면 아래와 같을 것이다.
master > git checkout -b feature/test
feature/test > git add .
feature/test > git commit -m 'fix typo'
2. 다음 날 출근해서 다시 남은 작업들을 하고, 퇴근 전에 또 commit을 남겼다면 아래와 같을 것이다.
feature/test > git add .
feature/test > git commit -m 'wip'
3. 다음 날 또 출근해서 열심히 일하면서 다 작업한 거 같아서, 테스트를 해보니 버그가 있다! 버그를 다 고치고 마지막 commit을 남겼다면 아래와 같다.
feature/test > git add .
feature/test > git commit -m 'bugfix'
4. origin에 push 하기 전에 rebase로 불필요한 commit을 squash해준다.
feature/test > git rebase -i @~3
(참고: -i는 --interactive 옵션이고, @~3은 최근 3개의 commit을 rebase하겠다는 뜻이다 HEAD~3과 같은 뜻이다.)
5. 그러면, 복잡해보이지만 아래와 같은 화면이 보인다. 필요 없는 commit은 s옵션으로 바꿔준다. 여기서는 commit 1개만 남겨보려고 한다. vi 에서 쓰는 명령어로 편집하면 된다!
(참고: 아래 내용 출처는 git-scm에서 퍼온 것을 수정한 것이다)
pick f7f3f6d fix typo
pick 310154e wip // 여기서 pick을 s로 바꿔준다.
pick a5f4a0d bugfix // 여기서 pick을 s로 바꿔준다.# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
6. 편집하면 아래와 같은 모습이다. 그리고 :wq로 vi를 빠져나온다.
pick f7f3f6d fix typo
s 310154e wip
s a5f4a0d bugfix# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
7. 그러면 아래와 같은 또다른 vi로 commit을 입력할 수 있게 된다.
# This is a combination of 3 commits.//이 위치에서 dd를 눌러 줄을 삭제한다.
# The first commit's message is: //이 위치에서 dd를 눌러 줄을 삭제한다.
Task 1/3 //이 위치에서 dd를 눌러 줄을 삭제한다.
# This is the 2nd commit message: //이 위치에서 dd를 눌러 줄을 삭제한다.
wip //이 위치에서 dd를 눌러 줄을 삭제한다.
# This is the 3rd commit message: //이 위치에서 dd를 눌러 줄을 삭제한다.
bugfix //나는 이 commit만 남기고 싶으므로 이건 냅둔다.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress;
8. 정리를 하면 이런 모양이다. 이 상태에서 :wq를 하면 rebase가 끝나고 브랜치로 다시 돌아오게 된다. git push origin feature/test로 push를 하고, 코드리뷰를 거친 뒤 master에 merge되는 방식으로 진행하고 있다.
bugfix
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress;
이렇게 git rebase를 하면 여러 commit을 남겼어도 꼭 필요한 commit만 남길 수 있어서 master의 commit 기록을 보면 커밋이 예쁘다.
주의할 사항은 다른 사람들과 함께 쓰고 있는 브랜치에다가 git push를 한 경우에는 가급적 rebase를 쓰지 않는 것이 좋다. 내가 rebase한 내용을 다른 사람이 git pull로 당겨 받으면 엄청난 conflict를 만날 수 있다. 😰 local에서 작업하고 origin으로 push하기 전에 깔끔하게 커밋을 정리하는 차원에서 이용하는 것이 좋다.