はじめに
筆者は恥ずかしながらgitコマンドでは大抵commit
とpush
しか使わず、訂正したいときでも commit --amend
するくらいです。
なので、ちょっと凝った(?)操作をするときに調べては忘れを繰り返していて、いい加減どうかと思うので初歩的な内容ばかりだと思いますがメモを残しておきます。(𝑛番煎じ ( 𝑛∈ℕ))
主にコミット履歴の改変についてのメモですが、それ以外のトピックも記載するつもりです。
新しく出会ったこと思い出したことあれば更新します。
空コミットする
まれにファイルに変更は加えたくないけれどコミットはしたいよという場合があります。
例えば、コミットを契機に何かの処理が動くのだけれどそれを動かすためだけに、アプリケーションの挙動を変えないような変更(適当な箇所にスペースや空行を入れるなど)を行ってコミットしたくない場合などでしょうか。
あるいはイニシャルコミットを空コミットにするなど。
こういった場合は--allow-empty
オプションを利用します。
$ git commit --allow-empty -m 'initial commit'
2つ以上前のコミットに差分を混ぜる
追加漏れファイルなどがあったりして、直前のコミットに差分を混ぜたいなというときにはcommit --amend
を使えばいいのですが、別のコミットを行った後で追加漏れに気づいた場合対応に困ります。
「追加漏れ」みたいなコミットメッセージでコミットしてもうるさく言われない環境であればそれでもいいのですが、ちょっと格好悪い気もします。
こういった場合rease -i
が使えるようです。
例として、下記のようなコミットの状況があったとして直近のコミット(7344f3fc)を「2番目のコミット」(94f9ffe8)に混ぜたい場合を考えてみます。
$ git log --oneline 7344f3fc 5番目のコミット 9fd223f8 4番目のコミット ced7e037 3番目のコミット 94f9ffe8 2番目のコミット 6ae9cb5d 1番目のコミット
2番目のコミットは4つ前のコミットになるのでHEAD~4
を指定してrebase -i
を実行します。
$ git rebase -i HEAD~4
下記のような内容でエディタが開きます。
pick 94f9ffe8 2番目のコミット pick ced7e037 3番目のコミット pick 9fd223f8 4番目のコミット pick 7344f3fc 5番目のコミット
5番目のコミットを2番目に混ぜたいので2番目のコミットの下に5番目のコミットの行を持ってきてpick
となっている箇所をf
にして保存します。
pick 94f9ffe8 2番目のコミット f 7344f3fc pick ced7e037 3番目のコミット pick 9fd223f8 4番目のコミット
これで、「5番目のコミット」が「2番目のコミット」に取り込まれました。
「1番目のコミット」のコミットハッシュは変わっていませんがそれより後のコミットのハッシュが変わっていることに注意してください。HEAD~4..HEAD
に含まれるすべてのコミットが(実際に変更したか否かに関わらず)書き換えられます。
$ git log --oneline 0a8cabf0 4番目のコミット 11262398 3番目のコミット ee9a0b7b 2番目のコミット 6ae9cb5d 1番目のコミット
既に共有リポジトリにプッシュしたコミットをここに含めると同じ変更内容のものが別のコミットとして見えるため混乱のもとになりますので、それは基本的には行わない方が良いようです。
コミットのrevert
開発していると、あるコミットの変更内容が不要になる場合が時々あります。
例えば、複数の機能をリリースするつもりでコミット積んでいたが一部機能はとある理由でリリースを見送りたいなどでしょうか。(機能毎に細かくブランチ切っておけという話もありましょうが。)
こういった場合には、revert
が利用できます。
下記のようなコミット履歴がありリリースを待っているような状況があるとします。
素敵な機能が揃っていて、リリースされればきっと顧客も満足するはずです。
$ git log --oneline 3565bbb9 great feature 2033f2f3 すごい機能2 174d2b16 powerful feature 0b18f6c5 awesome feature 5cbc3087 すごい機能1
ここで、「すごい機能2」に関してはまだ変更が入りそうで一旦リリースを延期してほしいとの連絡が来ました。
別ブランチを立てて「すごい機能2」を除いたコミットを一つ一つ再現するとかあるいはチェリーピックするとか考えらえそうですが、まぁ手間です。
「すごい機能2」のハッシュコミットを指定してrevert
してやることで当該コミットを打ち消すコミットを追加できます。
$ git revert 2033f2f3
$ git log --oneline 952c486d Revert "すごい機能2" 3565bbb9 great feature 2033f2f3 すごい機能2 174d2b16 powerful feature 0b18f6c5 awesome feature 5cbc3087 すごい機能1
また不要だからrevertしたのだけれどやっぱりその変更が必要だったみたいな場合も起こりうるでしょう。
revertされたコミットに対しても同じ要領でrevertが可能です。
マージコミットのRevert
参考: git revertでmerge commitを取り消す
revertしようとしたコミットがマージコミットだった場合エラーになります。
(-m
オプションがついてないといって怒られる。)
$ git revert aaaaaa error: Commit aaaaaa is a merge but no -m option was given
大雑把に言うと、マージしてるわけなので、切り戻すんならどっちを生かすの?ということらしく、それを-m
オプションで指定するようです。-m
オプションには1
または2
を基本的には指定するみたい。
-m オプションの値 | 意味 |
---|---|
1 | マージされた側のブランチ |
2 | マージする側のブランチ |
なので、マージしたコミットを戻す場合は1を指定する。
基本的には1を使うことが多いはず。
$ git revert -m 1 aaaaaa
(マージした・されたってわかりにくいな。図示した方がいいか?)