できない.dev

git commit --amend した後にプッシュできない

amend はコミット SHA を作り直すため、push 済みブランチで amend するとリモートと履歴が分岐し non-fast-forward で拒否される。
自分専用ブランチなら --force-with-lease、共有ブランチなら追加コミットで修正するのが原則。

公開: 更新:

症状できない · exit 1
git push origin main
…
error: failed to push some refs to '/tmp/tmp.JgiIMF/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.
解決後できた · exit 0
git push --force-with-lease origin main
To /tmp/tmp.JgiIMF/remote.git
 + 39b4642...0732de5 main -> main (forced update)

2026-09-29 に alpine/git(Git 2.54.0) で実際に打って取った出力。検証環境の詳細

要約

git commit --amend は コミット SHA を作り直す 操作なので、push 済みのコミットを amend すると履歴がリモートと分岐し、通常の push は non-fast-forward で拒否される。
自分専用ブランチなら --force-with-lease、共有ブランチなら amend ではなく追加コミットで修正、が安全な分岐点になる。

実行例

alpine/git のコンテナで push 済みのコミットを amend すると SHA が 39b4642 から 0732de5 に作り直され、そのままの git push は non-fast-forward で拒否されて終了コードが 1 になった。--force-with-lease を付けると forced update で上書きされて 0 が返り、amend 前の 39b4642 は git reflog にも残っている。

$ git commit -a --amend -m "init (amended)"
[main 0732de5] init (amended)
 Date: Tue Sep 29 01:07:52 2026 +0000
 1 file changed, 1 insertion(+)
 create mode 100644 app.txt
$ git push origin main
To /tmp/tmp.JgiIMF/remote.git
 ! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to '/tmp/tmp.JgiIMF/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.
$ echo $?
1
$ git push --force-with-lease origin main
To /tmp/tmp.JgiIMF/remote.git
 + 39b4642...0732de5 main -> main (forced update)
$ echo $?
0
$ git reflog --oneline
0732de5 HEAD@{0}: commit (amend): init (amended)
39b4642 HEAD@{1}: commit (initial): init

— 2026-09-29 時点の出力

検証環境Git 2.54.0 / 2026-09-29 検証
検証日
実行環境
alpine/git Alpine Linux v3.24
バージョン
  • Git 2.54.0

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

1. 自分専用ブランチでは --force-with-lease

git commit --amend
git push --force-with-lease origin feature/my-branch

git-push 公式ドキュメント(新しいタブで開く) のとおり、--force-with-lease はリモートが想定通りの SHA の時だけ上書きするので、知らないうちに他者の push を踏みつぶす事故を防げる。

2. 共有ブランチでは追加コミットで修正

# amend せずに普通の修正コミットを足す
git add fix.txt
git commit -m "fix: typo in previous commit"
git push origin main

main など共有ブランチでは履歴書き換えを避け、修正コミットを追加する。git rebase -i を使った履歴整理は、自分のブランチが PR にマージされる前に限定する。

3. 誤って amend した場合の復旧

git reflog
# 例:
# a1b2c3d HEAD@{1}: commit (amend): ...
# 0e9f8e7 HEAD@{2}: commit: ...   ← amend 前の SHA
git reset --hard 0e9f8e7

git-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 を既定にしておくと安全。

よくある原因

  1. amend で SHA 変化: メッセージ / ファイル変更が同じに見えても、内部的には新しい SHA を持つ別コミットになる。
  2. fast-forward 不成立: リモートの旧 SHA は新 SHA の祖先ではないため、Git は安全に取り込めず push を蹴る。
  3. オプション無し push: ただの git push では rewrite を反映できず、non-fast-forward で拒否される。
  4. 共有ブランチで amend: 他のメンバーが既に旧 SHA を取り込んでいると、後で衝突や重複コミットを生む原因になる。
  5. --force 素打ち: 他者の新規 push を上書きする事故になりやすい。
    共有ブランチで使うと履歴破壊。

この手順で直った?