GitHub 複数アカウントで push が404になる理由。commit authorと認証は別物

GitHub 複数アカウントで push が404になる理由。commit authorと認証は別物
会社用と個人用でGitHubアカウントを分けている人は多いと思います。会社のprivateリポと、個人のOSSや検証リポを行き来していると、ある日突然 push が通らなくなる。
fatal: repository 'https://github.com/.../....git/' not found
リポは確かに存在している。URLも間違っていない。さっきまで push できていた。なのに「リポジトリが見つからない」と404が返る。GitHubの障害を疑ったり、リポを消したっけと焦ったりした経験がある人向けに、この404の正体と切り分け方を書きます。
結論:404の正体は「認証アカウントのズレ」。commit authorとは別の話
先に答えを出します。private リポへの push が repository not found(404)で落ちるとき、犯人はたいてい gh CLI のアクティブアカウントが別人のままになっていることです。
ここで混同しやすいのが、commit author と push 認証の関係です。この2つは完全に別の軸で動いています。
項目 | 何を指すか | どこで決まるか |
|---|---|---|
commit author | このコミットを「誰が書いたか」 | git config の user.name / user.email |
push 認証 | GitHubに「誰としてアクセスするか」 | credential helper / gh のアクティブアカウント |
gitconfig で author を会社用メールに自動で切り替えていても、push のときにGitHubへ提示する認証情報は別の経路から来ます。author が正しく 会社のメールアドレス になっていることと、push が会社アカウントの権限で通ることは、まったく保証関係にありません。
credential helper(=gitが認証情報を保管して自動で使う仕組み)が個人アカウントのトークンを掴んでいれば、commit が会社名義でも、GitHubには個人として殴り込むことになります。

なぜ「not found」なのか:privateリポは権限の無い相手に存在しない

ここで「権限が無いなら403(Forbidden)を返せばいいのに、なぜ404なのか」と思った人は鋭いです。
GitHubは、private リポに対してアクセス権の無いアカウントには、そのリポの存在自体を隠します。「権限がありません」と返すと、リポ名やリポの存在がバレてしまう。private なのに「そこに何かはある」と漏らすのはセキュリティ上まずい。だから「そんなリポは無い」という顔をして404を返します。
つまり個人アカウントでアクセスした瞬間、会社のprivateリポはその個人アカウントから見て「存在しない」扱いになる。これが「リポは確かにあるのに not found」のからくりです。404という見た目に引っ張られて「リポが消えた」「URLが違う」と切り分けを始めると、延々と空振りします。
複数アカウントを使い分ける環境では、404を見たらまず疑うのはURLでもリポの存在でもなく、いま自分がどのアカウントとしてGitHubに繋がっているかです。
実話:commit authorは正しかったのに push が404で落ちた
実際にこれで詰まった話を書きます。
ある日、ローカルにある設定ファイルをバージョン管理に乗せようとして、会社のprivateリポへ初回 push を実行しました。返ってきたのは fatal: repository '...' not found、終了コード128。
最初に確認したのは commit author です。git config を見ると author は会社用のメールアドレスに正しく設定されていて、コミット自体も問題なく作られている。リポのURLも合っている。リポはブラウザから見えている。条件は揃っているのに push だけが404で落ちる。
犯人は gh CLI のアクティブアカウントでした。直前まで個人アカウント側で別の作業をしていて、アクティブが個人のままだった。つまりコミットは会社名義で作られているのに、GitHubへの認証だけが個人アカウントで走っていた。会社のprivateリポは個人アカウントから見えないので、GitHubは「そんなリポは無い」と404を返していた、というわけです。
この日もう1つ嫌な事故が重なりました。シェルの出力が乱れていて、おかしな文字列が混ざる状態だったため、失敗した push を「成功した」と早合点しかけました。出力の見た目で完了を判断するのが、いかに危ういかを思い知ったケースです。この検証の話は後の対処ステップで触れます。
対処:3ステップで切り分けて、機械的に完了を確認する

切り分けは3ステップで終わります。順番が大事です。
ステップ1: gh auth status でアクティブアカウントを確認する
push する前に、いま自分がどのアカウントとしてGitHubに繋がっているかを見ます。
gh auth status
複数アカウントをログインさせていると、出力の中に Active account: true が付いたアカウントが1つあります。これがいま push に使われるアカウントです。会社のprivateリポへ push するのに、ここが個人アカウントになっていたらアウト。404の8割はここで判明します。
push して404が出てから慌てるより、複数アカウント環境では push 前にこの確認を癖にしておくほうが速いです。
ステップ2: ズレていたら gh auth switch で切り替える
アクティブが目的のリポのオーナーと違っていたら、切り替えます。
gh auth switch --user <オーナー名>
gh auth switch はログイン済みのアカウント間を切り替えるだけなので、可逆です。やり直しもききます。会社リポなら会社アカウントを、個人リポなら個人アカウントをアクティブにしてから push する。これで「権限の無いアカウントで殴る」状態が解消されます。
切り替えたあと、作業が終わったら元のアカウントに戻すかどうかは、自分の運用次第です。会社作業が続くならそのままでいいし、すぐ個人作業に戻るなら戻しておく。
ステップ3: push の完了は git rev-parse の一致で確認する
ここが実話で痛い目を見た部分です。push が通ったかどうかを、シェル出力の「成功っぽい文字列」で判断してはいけません。出力が乱れる環境だと、失敗を成功と誤読します。
完了したかどうかは、ローカルとリモートのコミットハッシュが一致しているかで機械的に確認します。
git rev-parse HEAD # ローカルの最新コミット
git rev-parse origin/main # リモートの最新コミット
この2つが一致していれば push は確かに通っています。一致しなければ、見た目がどうあれ push は完了していません。1行で判定するならこうです。
[ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ] && echo OK || echo NG
人間の目視ではなく、ハッシュの突合で完了を確定させる。これだけで「push できたつもりで実は失敗していた」という最悪のパターンを潰せます。複数のアカウントやブランチを並行で扱うときほど、この機械的な確認が効いてきます。git運用の自動化や並行作業の設計については、Claude Codeとgit worktreeで複数ブランチを並行運用する設計でも触れています。
複数アカウント運用チェックリスト
会社と個人でGitHubアカウントを分けている人が、push まわりで事故らないための持ち帰りです。新しいリポを触り始める前と、push 前にこれを通しておくと、404でハマる確率がぐっと下がります。
- commit author を確認したか(
git config user.emailが、このリポのオーナーと整合しているか) - push 前に
gh auth statusを見たか(アクティブアカウントがリポのオーナーと一致しているか) - ズレていたら
gh auth switch --user <オーナー>で切り替えたか(可逆なので気軽に) - 404が出たら、まず認証アカウントを疑ったか(URLやリポの存在から疑い始めない)
- push 完了は
git rev-parse HEADとorigin/mainの一致で確認したか(出力の見た目で判断しない) - commit authorと認証は別軸だと理解しているか(authorが正しくても push が通る保証はない)
author の自動切り替えと認証の切り替えは別の仕組みなので、両方をそれぞれ整える必要があります。片方だけ正しくしても、もう片方がズレていれば事故る。
アンチパターン:404でハマる人がやりがちなこと
実際にやってしまった、あるいはやりがちな失敗を挙げます。
アンチパターン1: 「authorが正しいから push も通る」と思い込む
これが一番の落とし穴です。コミットが会社名義で作られているのを見て、push も会社の権限で通ると安心してしまう。実際には認証は別の経路で決まるので、author がいくら正しくても、アクティブアカウントが個人のままなら404で弾かれます。author と認証は別軸、とだけ覚えておけば防げます。
アンチパターン2: 404を「リポが消えた」「URLが違う」と早合点する
404という数字と「not found」という文言に引っ張られて、リポの存在確認やURLの打ち直しから始めてしまう。private リポは権限の無いアカウントには存在しない扱いになるので、リポもURLも正しいのに not found は普通に起きます。複数アカウント環境では、まず gh auth status を見るのが最短です。
アンチパターン3: 権限の無いアカウントのまま push を何度も再試行する
アクティブアカウントを直さないまま、ネットワークの問題かと思って push を連打する。原因が認証アカウントのズレである限り、何度叩いても404のままです。失敗したら手を止めて、原因の軸(認証なのか、リポなのか、ネットワークなのか)を切り分ける。再試行は原因を特定してからにします。
まとめ
GitHub 複数アカウント運用で push が404になる話を整理します。
- private リポへの push が
repository not found(404)で落ちる主因は、gh CLI のアクティブアカウントが別人のままになっていること - commit author(誰が書いたか)と push 認証(誰としてアクセスするか)は完全に別軸。author が正しくても push が通る保証はない
- private リポは権限の無いアカウントには存在しない扱いになるので、403ではなく404が返る
- 対処は
gh auth statusで確認 → ズレていたらgh auth switchで切り替え →git rev-parseの一致で完了を機械的に確認、の3ステップ
「commit が正しく作れている」と「push が正しく届いている」は別の話です。複数アカウントを跨ぐ環境では、この2つを分けて確認する習慣が、地味な404ハマりを防いでくれます。
複数アカウント運用や開発フローでお困りなら
会社と個人、あるいは複数クライアントでGitHubアカウントやリポジトリを使い分けていると、認証の取り違えやpushの事故は誰にでも起きます。チームでこの手のトラブルが繰り返し起きていたり、アカウント分離・権限設計を一度きちんと整理したい場合は、運用ルールごと見直すのが近道です。
f2t.jpでは、開発フローやリポジトリ運用の設計、こうした事故が起きにくい仕組みづくりをお手伝いしています。お問い合わせフォームから、現状の運用とつまずいているポイントをご相談ください。



