git rebase にはいくつかの使用パターンがある.

作成してから分岐元のブランチのコミットが進みすぎて古くなってしまったブランチを再度最新のコミットを基準にして生やし直す場合

以前 master ブランチから派生したブランチ dev があったときに、その後 master ブランチへのコミットが増えて master の最新コミットと dev の最新コミットとの間の差が 大きくなってしまった場合には git rebase を行うことで dev ブランチを master ブランチの最新コミットから再び分岐させ直して作ることができる.

$ git checkout dev
$ git rebase master

# コンフリクトした場合、コンフリクトを解消してから
$ git commit

# コンフリクト解消後、rebase を続行
$ git rebase --continue
* -> * -> *  [master]            * -> * -> *          [master]
   \                     ===>               \
     * -> *  [dev]                            * -> *  [dev]

Git でコミットしたあとにコミットメッセージを変えたくなった場合

直前のコミットのコミットメッセージを変更したいだけならば git commit --amend で対応できるが、2 つ以上前のコミットのコミットメッセージを変更したい場合には git rebase が必要となる.

  • まず、変更したいコミット よりも古いコミットのコミット ID をどれか 1 つ git log などを用いて調べる.

    • 一応、コミット ID を使わずともいくつ前のコミットなのかを把握しておけば HEAD~2HEAD~3 などを指定することでも対応可能.

  • 次に、 git rebase -i 調べたコミットID を実行する.

    • tig を使っている場合、現在の .tigrc の設定では main ビューか diff ビュー上で B キーを押すことで git rebase -i が起動するようになっている.

bind main B !git rebase -i %(commit)
bind diff B !git rebase -i %(commit)
  • vi エディタが起動し、指定したコミットまでの履歴が一覧表示される.

    • pick に設定されているコミットは git rebase 後のそのまま新たな履歴中でもそのまま採用される.

    • pick の他に fixupedit などがある. 各設定の意味は以下の通り.

# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified); use -c <commit> to reword the commit message
#
# 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.
#
  • 変更したいコミットについて、 pickedit に書き換えて :wq で vi エディタを終了する.

  • これにより、指定したコミットの状態にワーキングツリーが巻き戻ることとなるので、 git commit --amend を実行することでコミットメッセージを更新することができる.

  • git commit --amend 完了後、 git rebase --continue を実行することで rebase 処理を再開させる必要がある.

    • 複数のコミットを pick から edit に変更していた場合には、順番に各コミットの状態で止まることになるのでその都度 git commit --amendgit rebase --continue する必要がある.