git push が失敗したら、出力のうち ! で始まる行か、fatal: で始まる行を見ます。原因はほぼそこに書かれています。よく出る2つは、次の1行で直ります。
! [rejected] main -> main (fetch first)または(non-fast-forward)→git pull --rebase origin mainで取り込んでから、もう一度 pushfatal: The current branch ... has no upstream branch.→git push -u origin HEAD
以下は、このサイトの運営に使っているMac(macOS 26.6.2)で、2026年10月19日に一時フォルダの中だけで再現した出力です。GitHubなど外部のサーバーには接続せず、ローカルに作った空のリポジトリ(bare リポジトリ)を「リモート」として使いました。名前とメールアドレスはダミー(me / me@example.com)です。
再現の準備
remote.git をリモート役にして、そこから alice と bob の2つの作業フォルダを clone しました。2台のパソコンや、2人で同じリポジトリを触っている状況の代わりです。
$ git init --bare -q remote.git
$ git clone -q remote.git alice
$ git clone -q remote.git bob
$ cd alice
$ echo hello > README.md && git add README.md && git commit -qm "first"
$ git push origin main
To /tmp/itm78/remote.git
* [new branch] main -> main
成功したときは * や c4e8b1d..ac66f5a のような行が出ます。以下の失敗例と見比べると、どこを見ればいいかが分かります。
rejected (fetch first):リモートに知らないコミットがある
alice が push した後、それを取り込まずに bob でコミットして push しました。
$ git push origin main
To /tmp/itm78/remote.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to '/tmp/itm78/remote.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
終了コードは1でした。括弧の中の fetch first は「リモートに、手元でまだ一度も取得していないコミットがある」という意味です。別のPCや GitHub の画面上で編集してコミットした場合も同じ形になります。
rejected (non-fast-forward):取得はしたが取り込んでいない
git fetch だけして、もう一度 push しました。
$ git fetch -q origin
$ git status -sb | head -1
## main...origin/main [ahead 1, behind 1]
$ git push origin main
To /tmp/itm78/remote.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to '/tmp/itm78/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.
[ahead 1, behind 1] は「手元にだけあるコミットが1つ、リモートにだけあるコミットが1つ」。このままでは上書きになるので、Gitが止めています。
git pull がさらに止まる場合
hint のとおり git pull すると、今度は pull が止まりました(終了コード128)。
$ git pull origin main
From /tmp/itm78/remote
* branch main -> FETCH_HEAD
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
...
fatal: Need to specify how to reconcile divergent branches.
両方に別々のコミットがあるときに、マージで合わせるか、自分のコミットを相手の後ろへ付け直す(rebase)かを決めていないと出ます。個人の作業なら rebase が素直です。
$ git pull --rebase origin main
From /tmp/itm78/remote
* branch main -> FETCH_HEAD
Successfully rebased and updated refs/heads/main.
$ git log --oneline --graph
* ac66f5a bob work
* c4e8b1d first
$ git push origin main
To /tmp/itm78/remote.git
c4e8b1d..ac66f5a main -> main
--force で押し切ると、リモート側のコミット(ここでは first)を消すことになります。原因が分からないうちは使わないでください。
no upstream branch:新しいブランチの送り先が決まっていない
$ git switch -q -c feature/login
$ echo x > login.txt && git add login.txt && git commit -qm "login"
$ git push
fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin feature/login
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
終了コードは128。手元で作ったブランチには、まだ「リモートのどのブランチと対応するか」が登録されていないので、引数なしの git push では送り先が決まりません。-u を付けて一度 push すれば、以後は git push だけで済みます。
$ git push -u origin HEAD
To /tmp/itm78/remote.git
* [new branch] HEAD -> feature/login
branch 'feature/login' set up to track 'origin/feature/login'.
$ git status -sb | head -1
## feature/login...origin/feature/login
リモート自体が無い・パスが違う
リモートを登録していないリポジトリで push すると、次のどちらかになりました(どちらも終了コード128)。
$ git push
fatal: No configured push destination.
...
$ git push origin main
fatal: 'origin' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
$ git remote -v
(何も表示されない)
存在しないパスを origin に登録した場合も、ほぼ同じ文面です。違うのは、'origin' の部分が登録したURLになることだけです。
$ git remote add origin /tmp/itm78/no-such-repo.git
$ git push -u origin main
fatal: '/tmp/itm78/no-such-repo.git' does not appear to be a git repository
fatal: Could not read from remote repository.
どちらも、まず git remote -v で登録内容を確かめます。空なら git remote add origin URL、URLの綴りが違うなら git remote set-url origin 正しいURL です。GitHubの場合、URLの打ち間違いや、見る権限が無いプライベートリポジトリでは「Repository not found」になると GitHub のドキュメントに書かれています。対処として、URLはリポジトリのページからコピーして貼ることが勧められています。
src refspec … does not match any:送るブランチが手元に無い
$ git push origin mian
error: src refspec mian does not match any
error: failed to push some refs to '/tmp/itm78/remote.git'
ブランチ名の打ち間違いです(main を mian と打った)。まだ1回もコミットしていないリポジトリで git push origin main しても、同じ src refspec main does not match any になりました。このときは git status に No commits yet と出ます。
remote rejected:リモート側が受け取りを拒否した
リモート側の設定で弾かれる場合の形を見るため、bare リポジトリに「main への直接 push を拒否する」フックを置きました。GitHubの保護ブランチそのものではなく、同じ「サーバー側が拒否する」状況の代わりです。
$ cat remote.git/hooks/pre-receive
#!/bin/sh
# demo: refuse direct pushes to main (stand-in for a protected branch)
while read old new ref; do
if [ "$ref" = "refs/heads/main" ]; then
echo "main への直接 push は禁止です。ブランチを切ってプルリクエストを出してください" >&2
exit 1
fi
done
exit 0
$ git push origin main
remote: main への直接 push は禁止です。ブランチを切ってプルリクエストを出してください
To /tmp/itm78/remote.git
! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to '/tmp/itm78/remote.git'
ふつうの [rejected] は手元のGitが送る前に止めたもの、[remote rejected] は送った後にリモートが断ったものです。理由は remote: で始まる行に、サーバー側が書いた文面で出ます。GitHubでも、ブランチ保護ルールで直接 push やフォースプッシュが制限されていることがあります。その場合は手元をいじっても通らないので、別ブランチへ push してプルリクエストにします。
認証のエラー(今回は再現していない)
認証まわりは本物のアカウントを使わないと再現できないので、出力は載せず、公式ドキュメントで確かめた事実だけ書きます。
- GitHubにHTTPSで push するとき、パスワードを求められたら入れるのはGitHubのパスワードではなく personal access token です。Gitのパスワード認証は削除されています。
- Macでは、入力した認証情報が osxkeychain ヘルパーでキーチェーンに保存されることがあります。古いトークンが残っていると、新しいトークンを作っても古いほうが使われ続けます。GitHubのドキュメントでは、「キーチェーンアクセス」で
github.comを検索して消すか、git credential-osxkeychain eraseで消す方法が案内されています。
このMacには Git が2つ(Homebrewの /opt/homebrew/bin/git 2.54.0 と、Apple の /usr/bin/git 2.54.0 (Apple Git-157))あり、どちらにも git-credential-osxkeychain が入っていました。ターミナルでどちらが動くかはPATHの順番で決まり、このMacでは Homebrew が先でした。
終了コードの目安
今回の再現では、[rejected]・[remote rejected]・src refspec は終了コード1、fatal: で止まったもの(upstream が無い、リモートが無い、pull の方針が未設定)は128でした。スクリプトから push する場合の判定に使えます。
参考にした公式ドキュメント
- git-push Documentation(Git)
- リモートリポジトリについて(GitHub Docs):HTTPSでは personal access token を使う
- macOS キーチェーンからの認証情報を更新する(GitHub Docs)
- クローンエラーのトラブルシューティング(GitHub Docs):Repository not found の原因
- 保護されたブランチについて(GitHub Docs)
検証した環境
この記事の調査・再現・執筆は、運営者の指示のもとでAIエージェント(AnthropicのClaude)が行い、公開するかどうかは運営者が決めています。載せた出力は、そのAIエージェントがこのMacで実際にコマンドを実行して得たものです。
- macOS 26.6.2(Apple Silicon)
- Git 2.54.0(Homebrew)。グローバル設定を読まない状態(
GIT_CONFIG_GLOBAL=/dev/null、LANG=C)で実行 - リモートは一時フォルダ内の bare リポジトリ。外部サーバーへの接続なし(2026年10月19日)
コメントを残す