$ git commit --fixup <commit>

試しにGitの話でも。

最近Git 2.xの記事を読んでみて覚えた事を1つ紹介してみる。

japan.blogs.atlassian.com

この記事に書いてある 「git commit --fixup を利用して、素早い修正を」の部分をご紹介です。
↑の記事を読んでみて、翻訳のせいか理解するのに少し手間取ったので、その時間を短縮するか、理解の補助するお役に立てればと思った物です。元の記事を読んでわかる人には不要な物となります。

$ git commit --fixup

用途:
コミット履歴を修正するために使います。

前提条件:
rebase をするのでブランチを共有していない事。
つまりリモートにpushしていない事。

状況と使い方-手順:
例えば、ローカルの作業ブランチである程度作業を進めた後で、数個前のコミットにちょっとした間違いがある事に気付いた。(typoをしていたとか、消し忘れとか)
このような状況があったとして。

こうした場合でも、修正を新たにコミットして解決できますが、 コミット履歴をちょっと綺麗にしておきたいと考えた時には"--fixup"を使って直すこともできます。

以下のようなコミット履歴があったとして、 このA1のコミットの内容を修正したいとします。
(A1、A2、A3の部分はコミットメッセージの部分だと思ってください。)

commit: A3
commit: A2
commit: A1
checkout: topic_branchA

A1に適用したい修正をして、 それをコミットする際に --fixup を指定します。

$ git commit --fixup <A1のハッシュ>

適用したいコミットをオプション引数に渡します。
このコミットを確認すると以下のようなメッセージになっています。

fixup! A1

履歴の状態はこんな感じです。

commit: fixup! A1
commit: A3
commit: A2
commit: A1

そのあと引き続きこのブランチで必要な作業を完了させたとします。 

そして最後ですが、マージをする直前に先ほどのfixup!を適用するため
以下のように git rebase を行います。

$ git rebase --interactive --autosquash

一応簡単に補足
 --interactive :対話的に行うという指定。省略しても良いです。
 --autosquash :スカッシュの自動化みたいな事をします。

rebase完了後のコミット履歴を確認すると前の状態から、"fixup!"の付いたコミットが消えていて、その変更内容はA1に含まれている事になります。

commit: A3
commit: A2
commit: A1

以上で完了です。

--fixupというのが何をしているか簡単に説明すると [fixup! log_message] と言う形式でコミットにマークをつけることになります。
それがある状態で git rebase --autosqush をした際に fixup!のlog_messageに一致するコミットを修正対象として1つのコミットにまとめられます。
(そのコミットが、fixup対象としたコミットの直後に配置されて変更内容が適用される。) という事を git で半自動的に行ってくれます。

reflogを確認すると以下のようになってます。

rebase -i (finish): returning to refs/heads/topic_branchA
rebase -i (pick): A3
rebase -i (pick): A2
rebase -i (fixup): A1 //<< fixupしたコミットがこの順番に来ている。
rebase -i (pick): A1
rebase -i (start): checkout master

ちなみに、
* fixup! と似たもので squash! があります。
* 全く同じメッセージのコミットがあった場合の動作も一応確認しておきたい・・・。

余談

rebase についてはコンフリクトの修正でバグのコミットを隠してしまう可能性がある事に気をつけた方がいいかもしれません。 私の経験で、 rebase でコンフリクトを解消しながら完了させたあとにコミット履歴を見ると、そこでコンフリクトしていたという情報が欠落していた記憶があります。
(記憶違いだったら申し訳ないです。)
もっと正しい事例が↓この記事にあります。
https://frasco.io/why-you-should-stop-using-git-rebase-535fa30d7e25

ここにある通りマージしていくのが良いと思っています。正確な記録が残るので。
ただ、簡単な修正のためにfixupでrebaseするぐらいはあるかなと。