GitHub preflight
新しいリポジトリへのプッシュは、幾つかの退屈で繰り返し発生する方法で失敗し、エラーメッセージは問題の原因とは異なる箇所を指します。
src refspec main does not match any はブランチの問題のように聞こえますが、通常はコミットがないことを意味します。
仕事用アカウントで静かに成功したプッシュは、正しく成功したプッシュと見分けがつきません。
このスキルは、ユーザーが無駄なプッシュを行う前に、これらの問題を検出します。
基本原則:診断し、変更してはいけません。
調査結果を報告し、コピー&ペーストで実行可能な修正コマンドを提示します。
ユーザーがそれを実行します。
人々が複数のアカウントを維持するのは、どのアカウントが動作するかを気にしているからです。
そのため、こっそり git config や git remote set-url を代わりに実行するのは、まさに間違った直感です。
実行方法
bash <skill-dir>/scripts/preflight.sh [repo-path] [remote-name]
どちらの引数もオプションです。デフォルトはカレントディレクトリと origin です。
スクリプトは以下のコマンドのみを読み取ります:git config --get、ls-remote、ssh -T、push --dry-run。
書き込みは一切行いません。
何らかの理由でスクリプトが実行できない場合は、以下のチェックはそれぞれ1行で実行できます。直接実行して同じように解釈してください。
各チェックの意味
スクリプトは PASS / WARN / FAIL の行を出力します。
生の出力よりも解釈が重要なので、出力をそのまま貼り付けるのではなく、翻訳して伝えてください。
リポジトリ/ファイル/コミット。
空のディレクトリまたはコミットがないリポジトリは、プッシュ時に src refspec <branch> does not match any を生成します。
Gitは無からコミットを構築できません。
これは初回プッシュ失敗の最も一般的な原因なので、このエラーが発生した場合は最初に報告してください。
ブランチ。
git init を実行した直後は master ブランチにいる可能性があり、リモートが main を期待している場合があります。
名前の変更は最初のコミット 後 に安全に行えます(git branch -M main)。
unborn ブランチにはまだ名前を変更するものが何もないため、コマンドの順序を誤ると1サイクル無駄になります。
実効的なリモートURL。
正確に把握する価値があります。これは間違った方法でチェックしやすいからです。
git remote get-url は url.<base>.insteadOf を 既に展開 しており、git ls-remote --get-url も同様です。
したがって、これら2つを比較しても何も検出できません。
生の値は git config --get remote.<name>.url にのみ残るため、スクリプトはこれと git remote get-url --push(--push 形式は pushurl と pushInsteadOf もカバーし、実際にプッシュで使用されるもの)を比較します。
2つが異なる場合、ユーザーが設定したURLは、Gitが実際に接続するURLではありません。
典型的な落とし穴は、グローバルな url."https://github.com/".insteadOf = [email protected]: です。これはSSHをHTTPSに静かに迂回させ、したがってcredential helperに保存されているアカウント(多くの場合、ユーザーが意図したものとは異なる)にルーティングします。
常に実効的なURLを報告し、その違いを明示的に示してください。
認証アカウント。
SSHの場合、スクリプトは ssh -G を使用してホストを解決し( github-personal のようなホストエイリアスを実際のホスト名とキーに追跡します)、次に ssh -T でGitHubに直接問い合わせます。
GitHubは Hi <username>! と応答し、終了コード1を返します。ここでの終了コード1は失敗ではなく成功のケースです。
HTTPSの場合は、アクティブな gh アカウントを読み取ります。
そのアカウントをURLのオーナー部分と比較します。不一致は、プッシュが403になるか、間違った名前空間に到達することを意味します。
コミット作成者ID。
グローバル設定から継承された user.email は、静かに発生する障害です。
プッシュはあるアカウントとして認証される一方、すべてのコミットは別のアドレスで作成されます。
後で修正するには、修正または履歴の書き換えが必要になります。
リモートの所有者とは異なる所有者のリポジトリで、グローバルスコープのIDを検出した場合は、技術的にはまだ何も壊れていなくても、目立つようにWARNとして扱ってください。
リモートの状態。 リモートが空の場合、初回プッシュは正常です。 既存のrefがある場合、通常のプッシュはfast-forwardではないとして拒否され、ユーザーは最初にpull/rebaseする必要があります。拒否される 前に それを伝えてください。 ここでのエラーは通常、リポジトリが存在しないか、アカウントにアクセス権がないことを意味します。GitHubは両方を意図的に「見つかりません」と報告するため、推測するのではなく両方の説明を提供してください。
ドライランプッシュ。
コミットが存在する場合にのみ可能です。
これは実際のエンドツーエンドのチェックです。認証とrefネゴシエーションを実行しますが、書き込みは行いません。
欠点に注意してください。GH007(メールプライバシー)のようなサーバー側の拒否はキャッチしません。これらは実際の受信時に評価されるためです。
レポート方法
チェックの短いテーブルを表示し、次に失敗または警告があったものについてのみ、実行可能な順序で修正するための正確なコマンドを表示します。 合格したチェックを散文としてダンプしないでください。ユーザーは何が間違っていて、何を入力すべきかを知りたいのです。
IDを設定する必要がある場合は、マシンのデフォルトとはこのリポジトリが異なるというのが要点なので、グローバル設定に触れるよりもリポジトリローカルな設定を優先してください。
git config user.name "<account>"
git config user.email "<email>"
複数のリポジトリで同じ処理が必要な場合は、永続的な修正として includeIf を言及してください。
[includeIf "gitdir:~/personal/"]
path = ~/.gitconfig-personal
そして、プッシュが GH007 で拒否された場合は、個人のアドレスを推測するのではなく、GitHub → 設定 → メールにある @users.noreply.github.com アドレスを指摘してください。キーコメントやローカル設定はラベルであり、アカウントが受け入れるものの証明にはなりません。