コミットした直後に「メッセージを打ち間違えた」「追加するはずのファイルを入れ忘れた」と気づくことがあります。かといって「typo 修正」だけのコミットを積み重ねると、履歴がどんどん読みにくくなります。
そんなときに使うのが git commit --amend です。直前のコミットを作り直して、なかったことにできます。メッセージの修正にも、ファイルの追加・除外にも使える便利なオプションです。
この記事では、--amend の基本的な使い方から、ファイルの入れ忘れ・入れすぎの直し方、作者情報の修正、そして push 済みのコミットに対して使うときの注意点までを解説します。
目次
–amend は直前のコミットを作り直す
まず知っておきたいのは、--amend は既存のコミットを「編集」しているわけではない、ということです。実際には直前のコミットを捨てて、新しいコミットを作り直しています。
そのため、コミットハッシュは必ず変わります。見た目には同じコミットが1つあるだけですが、Git にとっては別物です。この性質が、あとで説明する「push 済みのコミットを amend するときの注意」につながります。
# amend 前
$ git log --oneline -1
9f3c1ab 検索機能を追加
$ git commit --amend -m "検索機能を追加"
# amend 後(ハッシュが変わっている)
$ git log --oneline -1
4d02e7c 検索機能を追加
コミットメッセージを書き直す
最もよく使うのがこの用途です。オプションを付けずに実行するとエディターが開き、直前のメッセージを編集できます。保存して閉じれば、その内容で作り直されます。
# エディターで編集する
$ git commit --amend
# コマンドラインで直接指定する
$ git commit --amend -m "検索フォームのバリデーションを追加"
ステージに何も追加していなければ、変わるのはメッセージだけです。コミットの中身(変更内容)はそのまま引き継がれます。
ファイルを入れ忘れたとき
git add し忘れたファイルがあった場合は、それをステージに追加してから --amend します。メッセージを変える必要がないなら --no-edit を付けると、エディターが開かずにそのまま完了します。
# コミットしたあとで、入れ忘れに気づいた
$ git status --short
M src/search.js
# 追加して、メッセージはそのままコミットし直す
$ git add src/search.js
$ git commit --amend --no-edit
[main 4d02e7c] 検索機能を追加
2 files changed, 43 insertions(+)
--no-edit は「メッセージを編集しない」という指定です。これを覚えておくと、細かい修正を前のコミットに吸収させる作業がとても速くなります。
間違えて含めたファイルを外す
逆に、コミットに含めるべきでないファイル(設定ファイルやデバッグ用のコードなど)を入れてしまった場合です。git rm --cached で Git の管理対象から外してから --amend します。
# コミットの中身を確認する
$ git show --stat --oneline HEAD
4d02e7c 検索機能を追加
src/search.js | 40 ++++++++++
.env.local | 3 +++
# .env.local をコミットから外す(ファイル自体は手元に残る)
$ git rm --cached .env.local
$ git commit --amend --no-edit
--cached を付けると、Git の追跡からは外れますが、ディスク上のファイルは消えません。うっかり --cached を忘れると実ファイルまで削除されるので、この2文字は忘れないでください。
今後もコミットしたくないファイルなら、あわせて .gitignore に追記しておきます。そうしないと、次の git add . でまた入ってしまいます。
ファイルの一部の変更だけを取り消したい場合は、そのファイルを直前のコミットの状態に戻してから、あらためてステージして amend します。
# デバッグ用の console.log を消して…
$ vim src/search.js
# 修正をステージして、直前のコミットに吸収させる
$ git add src/search.js
$ git commit --amend --no-edit
作者情報や日付を直す
複数のマシンで作業していると、user.name や user.email の設定を忘れたままコミットしてしまうことがあります。これも --amend で直せます。
# まず設定を直す
$ git config user.name "Taro Yamada"
$ git config user.email "taro@example.com"
# 現在の設定で作者情報を付け直す
$ git commit --amend --reset-author --no-edit
# 作者を直接指定することもできる
$ git commit --amend --author="Taro Yamada <taro@example.com>" --no-edit
Git のコミットには「作成者(Author)」と「コミット者(Committer)」の2つの情報があります。--reset-author は作成者を現在の設定で上書きし、作成日時も実行時点に更新します。
push 済みのコミットを amend するとき
ここが最大の注意点です。すでに push したコミットを --amend すると、リモートにあるコミットと手元のコミットが別物になり、そのままでは push できません。
$ git push
To github.com:example/repo.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:example/repo.git'
強制的に上書きするには --force が必要ですが、そのまま使うのは危険です。自分が最後に確認したあとに誰かが push していた場合、その変更を消してしまいます。
代わりに --force-with-lease を使ってください。「リモートが自分の把握している状態のままなら上書きする」という条件付きの強制 push です。
# 他の人の変更が入っていたら失敗してくれる
$ git push --force-with-lease
とはいえ、main のような共有ブランチで履歴を書き換えるのは避けるべきです。他の人がすでにそのコミットを取り込んでいると、全員の手元で履歴が食い違います。amend していいのは、まだ push していないコミットか、自分専用の作業ブランチだけと考えてください。
Pull Request のレビュー指摘を反映するときも、無理に amend せず、普通に修正コミットを積むほうがレビューしやすくなります。差分が追いやすく、レビュー済みの範囲も分かるからです。マージ時にまとめたいなら、GitHub の Squash merge を使えば履歴は1つにまとまります。
やり直しに失敗したときの戻し方
amend 自体を取り消したい
amend で上書きしてしまった元のコミットも、しばらくは git reflog から辿れます。HEAD がどう動いたかの記録が残っているので、amend 前の状態に戻せます。
$ git reflog
4d02e7c (HEAD -> main) HEAD@{0}: commit (amend): 検索機能を追加
9f3c1ab HEAD@{1}: commit: 検索機能を追加
28f9e36 HEAD@{2}: commit: READMEを更新
# amend 前のコミットに戻す
$ git reset --hard 9f3c1ab
commit (amend) と記録されている行のすぐ下が、amend 前のコミットです。git reset --hard は作業中の変更も消すので、必要なものが残っていないか確認してから実行してください。
直せるのは直前の1つだけ
--amend が対象にするのは HEAD、つまり直前のコミットだけです。2つ前、3つ前のコミットを直したい場合は使えません。その場合は git rebase -i で該当のコミットを edit や reword に指定します。
なお rebase -i の途中で edit を選ぶと、その時点で --amend が使える状態になります。「amend は直前のコミット専用、それ以外は rebase で目的のコミットを直前に持ってくる」と整理しておくと分かりやすいはずです。
エディターが開いて操作が分からなくなった
git commit --amend を実行して Vim が開き、抜け方が分からなくなることがあります。中断したいときは :q! と入力して Enter を押せば、amend は実行されずに終了します。保存して実行する場合は :wq です。
使い慣れたエディターに変えるなら、git config --global core.editor "code --wait" のように設定しておくと、以降は VS Code が開くようになります。
まとめ
git commit --amend は、直前のコミットを作り直すコマンドです。メッセージを直したいときはそのまま実行、ファイルを追加したいときは git add してから --amend --no-edit、含めすぎたファイルは git rm --cached してから --amend --no-edit。この3パターンを押さえておけば、日常の修正はほぼカバーできます。
注意すべきは、コミットハッシュが変わる=履歴の書き換えである点です。push 前なら気にせず使えますが、push 済みのコミットに対して使うと強制 push が必要になります。その場合も --force ではなく --force-with-lease を使い、共有ブランチでは避けるのが安全です。
間違えて amend してしまっても、git reflog を見れば元のコミットに戻せます。まずは自分だけのブランチで試して、感覚をつかんでみてください。