なぜ作ったか
ソースコードのバージョン管理などgit通常の使い方であれば全ての履歴をとっておきたいと思います。が、単に何世代かのバックアップをとっておきたいだけなら、古いコミットはまとめてしまって参照されなくなったファイルは.gitから消してディスク容量を抑えたいところです。ということでスクリプトを書いてみました。
ソース
https://github.com/hnakamur/git_squash_but_last_n_commits
に置きました。OS X 10.8.5 (Homebrewのgit 2.1.3とOS X標準のsed)とCentOS 6.6 (git 1.7.1とsed 4.2.1)で動作確認しました。
例
変更前
% git log
commit d08f035be73e38cfe20fdf492302ca0dab659f90
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:49 2014
Add hello6
commit 8424ea78bf5a9a5634b6a647b2088ff255ce452f
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:48 2014
Add hello5
commit aaa014a51dc1c4bcdc6ba82327eb12d230384c6a
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:43 2014
Add hello4
commit 2027c22669fb02734c4ae5e20a02d3823a393878
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:43 2014
Add hello3
commit cc4acfd45dfdc96cfc77cb063f7dde27f954bb6e
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:42 2014
Add hello2
commit 648a7d26a6bdb18cc795824499e8abd4e7e8e28b
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:30 2014
Initial commit
コミットをまとめる変更操作
最後の何個のコミットを残すかを引数に指定して git_squash_but_last_n_commits.sh
を呼び出します。
% git_squash_but_last_n_commits.sh 2
変更後
% git log
commit 752513b0c510bd69d143d91778936b74721ce6a2
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:49 2014
Add hello6
commit 3b0f962b9b10ecbab97db37e34c89b3e9ea0b892
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:48 2014
Add hello5
commit 504c12abe51fdc6b1fa38c7bce985c2449661957
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:42 2014
Add hello2
Add hello3
Add hello4
commit 648a7d26a6bdb18cc795824499e8abd4e7e8e28b
Author: Hiroaki Nakamura <hnakamur@gmail.com>
Date: Sat Nov 15 21:10:30 2014
Initial commit
実装メモ
git rebase -i を非インタラクティブに使う
stackoverflowに上がっていた回答を参考にしました。
git rebase -i
で編集する画面をsedで編集して pick
を適宜 squash
に変えてコミットをまとめています。
エディタの指定方法
元の例では環境変数 EDITOR
に設定していますが、 git config
で core.editor
を設定していると効きませんでした。そこで、元の core.editor
の値をとっておいて、 core.editor
の値を変更して git rebase -i
を実行し、その後 core.editor
の設定を元に戻すことで対応しています。
2014-11-16 00:25頃追記
@kyanro@github さんからのコメントで知ったのですが、git 1.7.2以降ならgit configで一旦変えて後に戻すという面倒なことをしなくても -c
オプションで1回のコマンド実行だけ値を指定することもできるそうです。しかし、CentOS 6.xでyumで入れたgitは1.7.1なので -c
は使えませんでした。そこで -c
オプションが使えるかどうかで分岐するようにしました。
最初のコミットはまとめないで残すことにした
最初OS Xで試した時のスクリプトでは git rebase -i --root
を使って最初のコミットも含めてまとめるようにしていました。
が、CentOS 6.6上のgit 1.7.1では You must specify --onto when using --root
と言ってエラーになってしまいました。ふと考えると、最初のコミットは残しておいたほうがgitレポジトリを作成した日時を後から確認できるので良いなと思い直して、残すのが仕様ということにしました。
履歴から参照されなくなったファイルをgit gcで削除
BFG Repo-Cleaner by rtyleyに書いてあった手順を真似しました。
$ git reflog expire --expire=now --all
$ git gc --prune=now --aggressive