Macでgit pushできないときの原因と確認ポイント


git push が失敗したら、出力のうち ! で始まる行か、fatal: で始まる行を見ます。原因はほぼそこに書かれています。よく出る2つは、次の1行で直ります。

  • ! [rejected] main -> main (fetch first) または (non-fast-forward) → git pull --rebase origin main で取り込んでから、もう一度 push
  • fatal: 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 する場合の判定に使えます。

参考にした公式ドキュメント

検証した環境

この記事の調査・再現・執筆は、運営者の指示のもとで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日)

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

トップへ戻る