git commit --amend した後にプッシュできない
amend はコミット SHA を作り直すため、push 済みブランチで amend するとリモートと履歴が分岐し non-fast-forward で拒否される。
自分専用ブランチなら --force-with-lease、共有ブランチなら追加コミットで修正するのが原則。
公開: 更新:
要約
git commit --amend は コミット SHA を作り直す 操作なので、push 済みのコミットを amend すると履歴がリモートと分岐し、通常の push は non-fast-forward で拒否される。
自分専用ブランチなら --force-with-lease、共有ブランチなら amend ではなく追加コミットで修正、が安全な分岐点になる。
よくある原因
- amend で SHA 変化: メッセージ / ファイル変更が同じに見えても、内部的には新しい SHA を持つ別コミットになる。
- fast-forward 不成立: リモートの旧 SHA は新 SHA の祖先ではないため、Git は安全に取り込めず push を蹴る。
- オプション無し push: ただの
git pushでは rewrite を反映できず、non-fast-forwardで拒否される。 - 共有ブランチで amend: 他のメンバーが既に旧 SHA を取り込んでいると、後で衝突や重複コミットを生む原因になる。
--force素打ち: 他者の新規 push を上書きする事故になりやすい。
共有ブランチで使うと履歴破壊。
解決策
1. 自分専用ブランチでは --force-with-lease
git commit --amend
git push --force-with-lease origin feature/my-branchgit-push 公式ドキュメント(新しいタブで開く) のとおり、--force-with-lease はリモートが想定通りの SHA の時だけ上書きするので、知らないうちに他者の push を踏みつぶす事故を防げる。
2. 共有ブランチでは追加コミットで修正
# amend せずに普通の修正コミットを足す
git add fix.txt
git commit -m "fix: typo in previous commit"
git push origin mainmain など共有ブランチでは履歴書き換えを避け、修正コミットを追加する。git rebase -i を使った履歴整理は、自分のブランチが PR にマージされる前に限定する。
3. 誤って amend した場合の復旧
git reflog
# 例:
# a1b2c3d HEAD@{1}: commit (amend): ...
# 0e9f8e7 HEAD@{2}: commit: ... ← amend 前の SHA
git reset --hard 0e9f8e7git-commit 公式ドキュメント(新しいタブで開く) でも amend は新しいコミットを作る挙動と明記されており、元の SHA はガベージコレクション前なら reflog から復元できる。
4. --force は単独で使わない
# NG: 他者の push まで上書きする
git push --force origin main
# OK: リモートが想定通りの時だけ上書き
git push --force-with-lease origin main共有リポジトリで素の --force を使うと履歴破壊の事故が起きる。
alias などで --force-with-lease を既定にしておくと安全。
実行例
実際に alpine/git 環境で上記の手順を動かすと、amend によって SHA が fdcd260 から 13666b4 へ作り直され、通常の push が non-fast-forward で拒否(終了コード 1)された後、--force-with-lease で forced update が成功(終了コード 0)することを確認できる。
warning: You appear to have cloned an empty repository.
push 済み SHA: 3cb5a58$ git commit -a --amend -m "init (amended)"
[main 884efb7] init (amended)
Date: Sun Aug 2 08:42:17 2026 +0000
1 file changed, 1 insertion(+)
create mode 100644 app.txt
amend 後 SHA : 884efb7$ git push origin main
To /tmp/tmp.bPOnBL/remote.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to '/tmp/tmp.bPOnBL/remote.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
push の終了コード: 1$ git push --force-with-lease origin main
To /tmp/tmp.bPOnBL/remote.git
+ 3cb5a58...884efb7 main -> main (forced update)
force-with-lease の終了コード: 0$ git reflog --oneline
884efb7 HEAD@{0}: commit (amend): init (amended)
3cb5a58 HEAD@{1}: commit (initial): init— 2026-08-02 時点の出力
検証環境
- 検証日
- 実行環境
alpine/git
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。