GitHubへ、
git push
したらエラーになった。
このとき、エラー文をそのまま検索して、
このコマンドを試す
↓
別のエラー
↓
また別のコマンドを試す
となることがあります。
Gitのpushエラーは原因が複数ありますが、最初にやることは意外と共通しています。
いきなり直そうとせず、現在の状態を確認する。
この記事では、pushできないときの確認順を、
状態確認
↓
原因候補を絞る
↓
必要な対処だけ行う
という流れで整理します。
まず最初に見る6つ
私はまず、次を確認します。
git status
git branch --show-current
git remote -v
git log --oneline --decorate -n 5
git fetch
git status
目的はそれぞれ違います。
| 確認 | 見たいこと |
|---|---|
git status |
未commit変更やGitの現在状態 |
git branch --show-current |
今どのbranchにいるか |
git remote -v |
どのGitHub Repositoryへ接続しているか |
git log |
直近のcommit |
git fetch |
GitHub側の最新情報 |
| エラー本文 | 状態と照合して原因を絞る |
git status はworking tree、index、未追跡ファイルなど現在の状態を確認する基本コマンドです。Git
1. そもそもpushするcommitがない
最初によくあるのがこれです。
ファイルを修正したつもりでも、
- 保存していない
-
git addしていない - commitしていない
ということがあります。
まず、
git status
を確認します。
例えば、
Changes not staged for commit:
なら、変更はありますがまだstageされていません。
必要なら、
git add .
git commit -m "変更内容"
git push
と進みます。
一方、
nothing to commit, working tree clean
で、pushすると、
Everything up-to-date
なら、Gitから見れば送る新しいcommitがない可能性が高いです。
ポイント
pushできない
と思っていても、実際には、
pushする変更自体がない
ケースがあります。
だから最初にgit statusを見ます。
2. 違うbranchにいる
次に確認したいのがbranchです。
git branch --show-current
例えば、
feature/login
で作業していたつもりなのに、
main
にいるかもしれません。
逆もあります。
branchを間違えた状態で、
git push
すると、意図したbranchとは別のものをpushしようとしてしまいます。
push前には、
git status
git branch --show-current
の2つを見るとかなり分かりやすいです。
3. upstreamが設定されていない
新しく作ったfeature branchを初めてpushすると、
upstreamがまだ設定されていない場合があります。
例えば、
fatal: The current branch feature/example has no upstream branch.
のようなメッセージです。
その場合は、
git push -u origin feature/example
とします。
-uは、そのローカルbranchと対応するremote branchを追跡関係にするための指定です。
一度設定されれば、次回からは通常、
git push
だけで済みます。
4. remote origin already exists
既存プロジェクトへGitHub Repositoryを接続するとき、
git remote add origin https://github.com/USER/REPO.git
を実行したら、
fatal: remote origin already exists.
と出ることがあります。
これは、
originという名前のremoteがすでに登録されている
という意味です。
GitHub公式でも、このエラーは既に同名remoteが存在する場合に発生すると説明されています。GitHub Docs
まず確認します。
git remote -v
例えば、
origin https://github.com/OLD/REPO.git (fetch)
origin https://github.com/OLD/REPO.git (push)
と出ます。
URLが正しい
そのままで問題ありません。
URLが間違っている
既存remoteを削除する前に、
git remote set-url origin https://github.com/USER/NEW-REPO.git
で変更できます。
GitHub公式もremote URL変更にはgit remote set-urlを案内しています。GitHub Docs
つまり、
origin already exists
↓
すぐ削除
ではなく、
origin already exists
↓
git remote -v
↓
今どこを指しているか確認
が先です。
5. rejected / non-fast-forward
代表的なpushエラーです。
例えば、
! [rejected] main -> main (non-fast-forward)
のような表示です。
これは多くの場合、
GitHub側に、自分のローカルがまだ持っていないcommitがある
状態です。
GitHubは履歴を失う可能性があるpushを拒否します。GitHub Docs
まずfetchする
git fetch origin
これでGitHub側の最新情報を取得します。
fetchはremote-tracking branchを更新しますが、自分の現在branchへ自動でmergeはしません。GitHub Docs
その後、状況を確認します。
git status
git log --oneline --decorate -n 10
必要なら、
git pull
でremote側の変更を取り込みます。
GitHub公式でも、non-fast-forward時にはfetchしてmergeするか、pullでまとめて取得・統合する方法が案内されています。GitHub Docs
--forceを最初の解決策にしない
ここは重要です。
non-fast-forwardを見ると、
git push --force
で押し切れる場合があります。
しかし、既存のremote履歴を書き換える可能性があります。
初心者向けの通常解決手順としては、
rejected
↓
fetch
↓
状況確認
↓
pull / merge等を検討
を基本にした方が安全です。
原因不明のままforce pushしない。
これだけは覚えておいた方がよいです。
6. conflictが起きた
git pullやmergeを行ったとき、同じ箇所が別々に変更されているとconflictが発生することがあります。
例えばファイル内に、
<<<<<<< HEAD
ローカル側の内容
=======
remote側の内容
>>>>>>> origin/main
のような表示が入ります。
この場合は、
- どちらの変更を残すか確認
- conflict markerを消す
- 正しい内容に修正
git add- commit
という流れです。
git status
を見ると、どのファイルがconflictしているか確認できます。
今回はconflictそのものの詳細には踏み込みません。
大事なのは、
conflictが出たら、別のコマンドを適当に打つのではなく、まず衝突しているファイルを見る
ことです。
7. detached HEADになっている
少し分かりにくい状態です。
例えば過去のcommitを直接checkoutしたあとなどに、
HEAD detached at ...
となることがあります。
これは、
通常のbranch上ではなく、特定commitを直接見ている状態
です。
まず、
git status
を確認します。
git branch --show-currentが何も返さないこともあります。
この状態で変更を続ける前に、
本当にこの状態で作業したいのか
を確認します。
通常のfeature branch作業へ戻るなら、
git switch main
や、
git switch feature/example
など、目的のbranchへ戻ります。
detached HEADの内部構造は今回は深掘りしません。
8. 認証エラー
push先やbranchが正しくても、GitHubへの認証に失敗してpushできない場合があります。
remote URLを確認します。
git remote -v
GitHubでは主に、
HTTPS
SSH
のremote URLを使います。GitHub Docs
HTTPSの場合は、パスワード認証そのものではなく、Personal Access Tokenやcredential helperなどを使用します。
SSHの場合はSSH鍵を使います。GitHub Docs
今回は認証設定自体は主題ではありません。
ただ、
branchもremoteも履歴も問題なさそうなのにpushできない
場合は、
認証も原因候補
として切り分けます。
9. GitHub側にsecretが含まれてpushを拒否されるケース
現在のGitHubでは、Push Protectionによりsecretが検出されたcommitのpushがブロックされる場合もあります。
GitHub公式では、対応対象のsecretが検出された場合、pushを止め、secretの削除または案内された手続きを行うよう説明しています。GitHub Docs
つまり、
pushできない
=
Gitの履歴だけが原因
とは限りません。
エラー本文は必ず読みます。
やらない方がいい対処
pushできないと焦ると、環境を大きく壊す操作を試したくなります。
初心者向けには、次を通常対処にしない方がよいです。
原因不明のまま --force
remote履歴を書き換える可能性があります。
.gitフォルダを削除
Git履歴や設定そのものを失います。
「よく分からないから初期化し直す」は最後の手段にします。
とりあえずcloneし直す
cloneし直すと一時的に直ったように見えても、
何が原因だったか分からないまま
になります。
originを確認せず削除
まず、
git remote -v
で確認します。
未commit変更があるままpullを繰り返す
先に、
git status
でローカル状態を確認します。
pushできないときの確認チェックリスト
最初にこれだけ見ると、かなり原因を絞れます。
git status
git branch --show-current
git remote -v
git log --oneline --decorate -n 5
git fetch
git status
そのうえで、
変更がない
→ commit状況を見る
branchが違う
→ 正しいbranchへ
upstreamなし
→ git push -u origin branch
originエラー
→ git remote -v
non-fast-forward
→ fetch → 状況確認 → pull等
conflict
→ 衝突箇所を解消
detached HEAD
→ branch状態確認
認証エラー
→ HTTPS / SSH設定確認
と進めます。
まとめ
GitHubでpushできないとき、
大事なのはエラー別の解決コマンドを大量に覚えることではありません。
まず、
status
↓
branch
↓
remote
↓
log
↓
fetch
↓
エラー本文
の順で現状を整理する。
その後に、
必要な対処だけ選ぶ。
この順番にすると、
何となくコマンドを試して、さらに分からなくなる
状態をかなり避けやすくなります。
Gitでは、
「直す前に状態を見る」
のが一番重要なのかもしれません。