git rebase 로 커밋 정리하기

발생일: 2014.11.20

키워드: git, rebase

문제:
작업하던 내용을 작은 단위로 쪼개 커밋했다가,
의미있는 단위로 모아서 서버에 푸시하려고 한다.

git rebase 로 커밋을 정리할 수 있는 걸로 알고 있고,
여러 번 해보긴 했는데 이건 늘 할 때마다 헷갈린다.


해결책:

`git rebase`에 대한 자세한 설명은 아래 참고 문서에서 확인할 수 있다.
여기선 'rebase 인터랙션 도구로 여러 커밋을 한 개의 커밋으로 정리’하는 과정을 기술하는 것으로 설명하려 한다.

1. 먼저, 지금까지의 커밋 로그를 확인한다.

    $ git log
    8fde911 - Sixth commit
    9f3e2b8 - Fifth commit
    1d02857 - Fourth commit
    7ee8f67 - Third commit
    bbb5c5d - Second commit
    37aa5cc - First commit


2. 정리할 커밋 로그를 확인한 후에, rebase 할 대상을 정해서 인터랙티브 도구로 rebase 한다.
  -i 옵션이 인터랙티브 옵션이고, `HEAD~5`는 rebase 대상 커밋을 의미한다.
  위 코드에선 `HEAD~5`와 같은 식으로 대상을 정했는데,
  '현재 커밋의 몇 번째 부모’를 의미한다.
  rebase를 실행하면 아래와 같이 vi 에디터에, 커밋과 각 커밋에 수행할 명령에 대한 설명이 출력된다.

    $ git rebase -i HEAD~5
    + .g/r/git-rebase-todo
       22 pick bbb5c5d Second commit
       21 pick 7ee8f67 Third commit
       20 pick 1d02857 Fourth commit
       19 pick 9f3e2b8 Fifth commit
       18 pick 8fde911 Sixth commit
       17
       16 # Rebase 37aa5cc..8fde911 onto 37aa5cc
       15 #
       14 # Commands:
       13 #  p, pick = use commit
       12 #  r, reword = use commit, but edit the commit message
       11 #  e, edit = use commit, but stop for amending
       10 #  s, squash = use commit, but meld into previous commit
        9 #  f, fixup = like "squash", but discard this commit's log message
        8 #  x, exec = run command (the rest of the line) using shell
        7 #
        6 # These lines can be re-ordered; they are executed from top to bottom.
        5 #
        4 # If you remove a line here THAT COMMIT WILL BE LOST.
        3 #
        2 # However, if you remove everything, the rebase will be aborted.
        1 #
        0 # Note that empty commits are commented out

  에디터의 맨 윗 라인을 보면 두 번째 커밋부터 여섯 번째 커밋(`HEAD~5`)까지 각 커밋이 나열되어 있고,
  각 커밋에 `[명령] [커밋] [설명]`와 같이 기재되어 있다.
  해당 `[커밋]`에 `[명령]`을 수행하겠다는 의미이고,
  `[명령]`의 문자열을 직접 변경하는 식으로 rebase를 진행할 수 있다.
  예를 들어, `pick bbb5c5d`는 현재 커밋을 rebase의 기준으로 사용하겠다는 의미이고,
  `edit bbb5c5d`와 같이 문자열을 바꾸면 해당 커밋에 다른 명령을 수행할 수 있다.


3. 지금은 특정 커밋을 기준으로 다른 커밋들을 하나로 합치려고 한다.
  가장 이전의 커밋을 기준(`pick`)으로, 나머지 커밋들을 이전 커밋에 합하면(`squash`) 된다.
  각 명령은 약어로도 가능하며, 위 경우엔 아래와 같이 바꿔주면 된다.

    + .g/r/git-rebase-todo
       22 pick bbb5c5d Second commit
       21 s 7ee8f67 Third commit
       20 s 1d02857 Fourth commit
       19 s 9f3e2b8 Fifth commit
       18 s 8fde911 Sixth commit

  위와 같이 수정하고 저장하면, 선택한 커밋의 메시지를 설정하는 화면으로 변경되고,
  커밋 메시지를 정리하고 저장하면 rebase가 완료된다.


4. 깃 로그를 다시 확인해보면, 최근 5개 커밋이 새 커밋으로 합쳐진 것을 볼 수 있다.

    $ git log
    6745e78 - Rebase onto second commit
    37aa5cc - First commit



몇 가지 팁.
- rebase 중 잘못 선택하거나 실수로 의도하는 것과 달라진 경우엔,
  `git rebase --abort`로 rebase를 취소할 수 있다.
- rebase 중 머지가 깨진 경우엔, 해당 파일을 수정하고 add 한 후,
  `git rebase --continue`로 계속할 수 있다.
- `squash`나 `fixup`은 이전 커밋을 대상으로만 수행할 수 있다.
  최근 커밋을 이전 커밋으로 합하는 명령이기 때문이다.
- 절대로. 이미 푸시했던 커밋을 대상으로는 rebase 하지 않는다.




참고:
쉽게 잘 설명해놓은 블로그가 있다.
http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

git pro book의 git rebase에 대한 설명이다.




카테고리

분류 전체보기 (711)
About me. (6)
Daylogs (676)
영어공부 (0)
My works - 추억 (29)
비공개 (0)