開発ブログ

WWWクリエイターズが送る、Git、CSS、HTML、コマンドライン、Macの便利機能など、開発に関する役立ち情報発信します。気まぐれに更新。

git のコミットをまとめて、履歴を綺麗にするコマンド

最終更新:2017-10-05 by Joe

Gitで、不用意にたくさん作ってしまったコミットを1つにまとめて、履歴をきれいにする方法です。

コミットをまとめる「git rebase -i」

ローカルで開発中は、バックアップの目的を兼ねて、ついついgit commitを連発してしまいます。そうすると、自然にどんどんコミット履歴が乱れていきます。そんなじょうきょうでも、「git rebase -i」 を実行すれば、コミット履歴は、後からいくらでも修正できるのです。

// インタラクティブモードでリベース
git rebase -i <コミット>

このコマンドにより、現在のブランチの先頭から、指定したコミットまでの歴史を一つずつ整理することができるのです。

それでは、実際に順を追って見ていきましょう。下記は現在チェックアウトしているブランチです。

コミットAの後に続く複数のコミットをまとめたい場合、「git rebase -i <commit-A>」を実行します。A移行のコミットがひとつずつ、順番に適応し直されていきます。

「-i」は「--interactive」の略で、この時1つずつ、どのようにコミットを処理するかを、個別に指定することができます。

[実践編] 実際にまとめてみる

それでは、実際に試してます。下記の状態から、一番古い「307028b」に対してリベースをかけます。

// ログをツリーで出力
$ git log --graph --oneline

// 出力
* 8274a1c (HEAD -> refs/heads/master) Add the email field to the contact form.
* 14776e2 Fix the bugs in the mobile UI.
* 02f1a92 Add the link to the admin panel.
* 3e89043 Add ga event to the mobile UI.
* 307028b Merge branch 'feature/topic-a' into master

実際の「git rebase -i 307028b」を実行します。テキストエディタが起動しますが、コミットがさきほどのツリーと逆向きになります。上から、コミットを再適応する順番なので、古いコミットから、新しいコミットの順番に並んでいる事に注意して下さい。

// 実行
$ git rebase -i 307028b

// テキストエディタが起動して、以下を編集。
pick 3e89043 Add analytic event to the mobile UI.
pick 02f1a92 Add the link to the admin panel.
pick 14776e2 Fix the bugs in the mobile UI.
pick 8274a1c Add the email field to the contact form.

# Rebase 307028b..8274a1c onto 307028b (4 commands)
#
# 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
#
# 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

あとは、それぞれの行の指定を好きなように書き換えて、エディタを保存して終了すればOKです。下の方に、説明が書いてありますので、操作にそれほど迷うことは無いかと思います。

指定説明日本語
p, pickuse commitコミットを利用する
r, reworduse commit, but edit the commit messageコミットを利用する、でもコミットメッセージを編集
e, edituse commit, but stop for amendingコミットを利用する、でもコミットを修正する(ステージにあるが、git commit されていない状態)
s, squashuse commit, but meld into previous commitコミットを利用する、でも直前のコミットに統合
f, fixuplike "squash", but discard this commit's log messagesquashと似ているが、コミットメッセージをを破棄する
x, execrun command (the rest of the line) using shellこの行の末尾に指定したシェルコマンドを実行
d, dropremove commitコミットを破棄する

今回の、「コミットをまとめる」という目的においては「fixup」もしくは「squash」が非常に適しています。この2つはそれほど大きな違いはありませんが、squashでは、コミットメッセージを書き直すようにエディタが起動するのですが、2つのとコミットメッセージがデフォルトでエディタ内に記載されています。一方でfixupには、直前のコミットメッセージしかありません。

整理した履歴をPush するとき

もし、rebase -i によって修正する前の履歴をすでにリモートにPush済だったときは、少し注意が必要です。修正前の履歴と、修正後の履歴が、コンフリクトしてしまうからです。

もし、リモートの歴史の書き換えが問題ない状況の時は、下記のコマンドで強制的にリモートを書き換えてしまいましょう。チームで開発している方は、このような操作の前に必ずチームメンバーと相談して下さい。

// 強制的にPushする
git push -f origin <Branch name>

以上です。

参考

git rebase の仕様です。

 

閉じる