일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- css
- 소스트리
- WEB
- Nodejs
- fixed
- Box Model
- workflow
- Express
- route
- git checkout
- React
- rbenv
- sourcetree
- Advanced
- Reset
- crud
- Merge
- git
- git branch
- Develop
- Process
- commit
- linux
- relative
- Basic
- Teamwork
- html
- Rebase
- Remote
- root
- Today
- Total
Codesigner
[Git] Git Advanced - Rebase -i 활용법 본문
저번 포스팅에서 rebase 가 무엇이고, 어떻게 활용하는지 알아보았다. 간단하게 정리해보자면, 브랜치를 병합하는 merge와는 또 다른 방법으로 각 커밋들의 변경 사항들을 차례대로 basebranch에 반영하여 결과적으로 선형적인 커밋 히스토리를 만들어 내는 기능이었다. 이번 포스팅에서는 이러한 작업을 대화형(interactive) 인터페이스를 제공함으로써 좀 더 정교한 작업을 가능하게 해주는 -i
옵션에 대해 알아보도록 하자
git rebase -i
git-scm에서는 -i
옵션에 대해 다음과 같이 설명하고 있다
Make a list of the commits which are about to be rebased. Let the user edit that list before rebasing. This mode can also be used to split commits
직역하면 rebase 될 커밋들의 리스트를 사용자가 편집할 수 있게 해 준다는 뜻이다. 아직 그 개념이 잘 잡히지 않는데, 다음과 같은 Git 환경을 만들고 실습하면서 더 자세히 알아보도록 하자. 현재 Git 프로젝트의 커밋 히스토리는 다음과 같다
이제 이 커밋 리스트를 rebase 해보도록 하자. 이때 rebase 할 커밋의 범위를 지정해야 하는데, 이를 일반화한 명령은 다음과 같다
git rebase -i <작업할 커밋의 직전커밋>
이 말의 의미는 git rebase -i
의 파라미터로 주어진 커밋의 바로 다음 커밋부터 HEAD까지 rebase를 진행한다는 뜻이다. 만약 HEAD~3을 파라미터로 준다면 HEAD~2, HEAD~1, HEAD를 rebase 하겠다는 의미이다. HEAD~3을 파라미터로 준 결과 다음과 같이 편집기가 실행된다
편집기의 상단에 rebase할 커밋들의 리스트가 나타난다. 아래에는 주석으로 몇 가지 명령어들이 나열돼 있는데, 이 명령들을 활용하여 커밋들을 자신의 입맛대로 rebase 할 수 있다. 지금부터 각 명령어들의 기능이 무엇인지 알아보도록 하자
pick
pick 은 고른다, 선택한다는 의미로 해당 커밋을 히스토리에 사용하겠다는 말이다. 현재 기본적으로 모든 커밋들이 pick 된 상태로 히스토리에 존재하고 있다
이 상태에서 커밋의 순서를 바꿀 수도 있고, 해쉬값을 이용하여 커밋을 가져올 수도 있다. 2번째(Add apple)와 3번째(Add cherry) 커밋을 바꿔보도록 하자
저장하고 종료한 뒤 로그를 살펴보면 변경된 내용으로 커밋 히스토리가 작성되어 있는 걸 확인할 수 있다
<그림 1>과 비교해서 보면, banana와 cherry의 커밋 해쉬값이 둘 다 변경된 걸 확인할 수 있다. 이는 내용은 같지만 완전히 새로운 커밋이란 걸 의미한다. 앞에서 커밋의 해쉬값을 이용해 커밋을 가져올 수 있다고 하였는데, 이를 테스트하기 위해 새로운 커밋을 작성하도록 하자
지금 필자가 하고자 하는 것은 방금 생성한 커밋을 git reset
명령으로 되돌린 뒤 rebase의 todo 리스트에 해당 커밋 해쉬값을 가져와서 히스토리에 추가하는 것이다
git reset --hard HEAD~
로그를 다시 확인해보면 방금 생성한 커밋이 삭제된 걸 확인할 수 있다. 이제 git rebase -i HEAD~3
명령으로 편집창을 실행시키자. 조금 전에 생성한 커밋의 해쉬값은 d3816e0
이므로 이를 pick 하는 줄을 추가하도록 하자(해쉬값이 기억이 안 난다면 git reflog
명령으로 확인할 수 있다)
자, 이제 다시 로그를 확인해보면 삭제했던 커밋이 히스토리에 추가된 것을 확인할 수 있다(우와)! 또한 ls
명령으로 working directory를 확인해보면 해당 커밋의 작업 내용이 추가된 것도 확인할 수 있다
rebase는 이런 강력한 기능을 제공한다... 안 쓰고는 못 배기지 않겠는가?
reword
reword는 커밋의 메시지를 변경하는 명령이다. 메시지를 변경할 커밋의 해쉬값 앞에 reword 키워드를 적어주면 해당 커밋의 메시지를 다시 작성하는 창이 열린다. 여기서는 apple의 메시지를 변경해보도록 하자
저장하고 종료하면 apple 커밋의 메시지를 변경할 수 있는 편집창이 열린다. 메시지를 변경하고 저장하면 커밋 히스토리에서 변경된 커밋 메시지를 확인할 수 있다
단순히 HEAD 커밋의 메시지를 변경하고 싶으면 git commit --amend
명령을 사용하면 된다
edit
reword 가 메시지만 변경하는 작업이었다면 edit 은 커밋의 작업한 내용까지 변경할 수 있는 명령이다. 나의 경우 git rebase -i HEAD~4
명령을 실행한 후 dragonFruit 커밋의 명령을 edit으로 바꿔주었다
저장하고 종료하면 해당 커밋으로 checkout 되고, 작업을 수행할 수 있게 된다. 나의 경우 dragonFruit.txt를 삭제하고 donut.txt를 추가해 주었다
그리고 다음 명령을 실행하여 커밋을 완료한다
git add .
git commit --amend
커밋 메시지도 변경하고 싶다면 마지막 명령 이후에 열리는 편집창에서 변경하면 된다. 나의 경우는 Add donut으로 메시지를 변경해 주었다. rebase를 계속하려면 다음 명령을 실행한다
git rebase --continue
커밋 히스토리를 확인해보면 다음과 같다
donut 메시지의 커밋이 dragonFruit 대신 히스토리에 나타나는 것을 확인할 수 있다
squash
squash는 해당 커밋을 이전의 커밋과 하나로 합치는 명령이다. 즉, 여기서 donut 커밋에 squash 명령을 적어주면 이전 커밋인 cherry와 하나로 합쳐진다
저장하고 종료하면 커밋 메시지를 변경할 수 있는 편집창이 나타난다. 그대로 저장하면 기존의 메시지가 그대로 하나의 커밋으로 히스토리에 나타나는 것을 확인할 수 있다
fixup
fixup은 squash와 동일하게 이전 커밋과 합치는 명령이다 squash와 다른 점은 메시지는 합치지 않는다는 것으로, 이전 커밋 메시지만 히스토리에 남게 된다. 이 점을 제외하곤 squash와 동일하다
exec
exec 명령은 각 커밋이 rebase 된 후 실행될 쉘 명령을 지정할 수 있다. 필자의 경우 다음과 같이 각 커밋 리스트 사이에 exec 명령을 추가해서 커밋의 해쉬값과 메시지를 echo 하게 하였다
저장하고 종료하면 다음과 같은 결과를 출력한다
drop
drop 은 커밋 히스토리에서 해당 커밋을 삭제하는 명령이다. 필자와 같이 편집창에서 커밋 앞에 drop 키워드를 적어주면 해당 커밋은 rebase 된 히스토리에 포함되지 않는다
저장하고 종료한 뒤 커밋 히스토리를 보면 해당 커밋이 삭제된 걸 확인할 수 있다
사실 커밋 리스트 편집창에서 한 줄을 지워줘도 같은 기능을 한다
Generalizations
지금까지 git rebase -i
를 활용하는 방법과 관련된 명령어들을 알아보았다. 배운 내용들을 정리하면 다음과 같다
git rebase -i
는 rebase 될 커밋 리스트를 직접 편집할 수 있게 해주는 기능이다git rebase -i commit_sha
- 주어진 해쉬값의 커밋 이후부터 HEAD까지 rebase 한다git commit --amend
- HEAD 커밋을 수정한다. 또한 rebase 중 커밋의 편집을 완료한다git rebase --continue
- 커밋을 편집한 뒤 rebase를 계속한다
우리는 또한 커밋 리스트를 편집하는 여러 명령어들을 알아보았는데, 각 명령어들의 기능은 다음과 같다
-
pick
- 해당 커밋을 히스토리에 넣는다 -
reword
- 해당 커밋의 메시지를 변경한다 -
edit
- 해당 커밋의 메시지와 작업 내용을 변경한다 -
squash
- 해당 커밋을 이전 커밋과 하나로 합친다 -
fixup
- 해당 커밋을 이전 커밋과 하나로 합친다. 단, 메시지는 이전 커밋의 메시지로 합쳐진다 -
exec
- 쉘 명령을 실행한다 -
drop
- 커밋을 히스토리에서 삭제한다
처음에는 rebase의 개념이 잘 잡히지 않고 사용하기도 꺼려지지만, rebase에 익숙해지면 merge보다 더 자주 사용하게 될 것이다. 또한 로컬에서 작업하고 커밋 히스토리를 정리하고 싶을 때 rebase가 유용하게 쓰이고, -i
옵션을 이용해서 원하는 작업을 수행할 수 있을 것이다
'Git > git' 카테고리의 다른 글
[Git] Git Advanced - Rebase overview (0) | 2019.04.16 |
---|---|
[Git] Git Advanced - 태그(tag)의 생성, 조회, 서명 그리고 검증 및 공유 (0) | 2019.04.15 |
[Git] Git Teamwork - Workflow & Generalizations (0) | 2019.04.09 |
[Git] Git Teamwork - Remote Repository (0) | 2019.04.09 |
[Git] Git Branching - Merge conflict & Review (0) | 2019.04.09 |