git rebase -i のコマンド

git rebase -i するとこのようなメッセージが表示されると思います。これらの動作についてです。

# 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
# d, drop = remove commit

こなみにこれらは、一旦指定コミットまで戻った上で上(古いコミット)から下(新しいコミット)に処理されていきます。

p, pick

デフォルトではこれになっていると思いますが、これはそのままそのコミット内容を再適用するということになります。

r, reword

これを指定したコミットの適用前にエディターが開いてコミットメッセージを変更できます。

e, edit

そのコミットをgit commit --amendしたあとの状態で待機させます。git statusを実行すると以下のようになります。

You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

何かやりたいなら再度git commit --amendなどで取り入れ、git rebase --continueで次のコミットへ移動します。

s, squash

そのコミットのメッセージとpush内容をを一つ前のコミットに含ませ、この単体のコミットはなかった事にします。

例えば以下のような履歴だとします。

git diff HEAD~1 --name-only
# a.js
git log --oneline | sed -n 1p
# 977fa06fc add b.js

git diff HEAD~2 --name-only
# b.js
git log --oneline | sed -n 2p
# 90490591b add a.js

そしてgit rebase -i HEAD~2を実行して以下のように編集してから閉じます。

pick 977fa06fc add a.js
s 90490591b add b.js

すると以下のようなまとめるコミットのメッセージ編集が立ち上がるので、適当に閉じます。

# This is a combination of 2 commits.
# This is the 1st commit message:
add a.js
# This is the commit message #2:
add b.js

...

f, fixup

squashと似てますが、そのコミットのpush内容だけが対象です。メッセージは単に捨てられます。
また、rebase後のコミットのメッセージ編集も立ち上がりません。

x, exec

完全にやり直したい場合に使えます。そのコミット内容を完全に捨ててしまい、やりたければまったく新しいコミットをその場で作成・適用ができます。このコマンドの実行時にはそのタイミングで待機状態になります。以下はそのときのgit statusの例です。

git status
# interactive rebase in progress; onto 02063c9
# Last commands done (3 commands done):
#    pick 18819b7 foo
#    exec bcac294 bar
#   (see more in file .git/rebase-merge/done)
# Next command to do (1 remaining command):
#    pick 403a6aa baz
# You are currently editing a commit while rebasing branch 'master' on '02063c9'.
#   (use "git commit --amend" to amend the current commit)
#   (use "git rebase --continue" once you are satisfied with your changes)

nothing to commit, working tree clean

「いいタイミングでgit rebase --continueしてください」とあります。何もせずにそれを実行すると次のセクションのd, dropを適用した時と同じになります。「元コミットに無を適用した」ということで何もなかったことにしたような感じです。

このタイミングのソースの状態は、このx, execを適用する前の状態です。例えば、ある時点からあるバグが起こるようになってしまいその検証の為に、「怪しいある時点に戻って、その時の状態でチェックしていく」ような時に使えると思います。(そしてgit rebase --abort。。。)

d, drop

単にそのコミットを削除します。

これはたまにmasterを経由しなければいけないのに、平行で作業中のブランチから新しいブランチと移動してしまい作業中だったブランチの内容を持ってきてしまった時にブランチを作り直さなくても良くなったりします。

allow-empty は表示されない

これを調べる時に--allow-emptyコミットを作って確認しようと思ったのですが、一覧に表示されませんでした。駄目みたいですね。