本文へ移動
cccskills
無料GitHub で公開

gh-fetch

非対話セッション(claude-code の remote-control / CI など TTY が無く SSH 鍵パスフレーズを入力できない状況)で git fetch / pull を通すスキル。

remote が SSH URL で `ssh -o BatchMode=yes` による非対話 SSH 認証が実際に通る(agent の鍵・パスフレーズ無しのディスク鍵・macOS キーチェーン鍵のいずれでも可)なら素の SSH fetch を実行し、非対話 SSH 認証が通らず `git fetch`/`git pull` が `Permission denied (publickey)` で失敗する場合は、取り込みを HTTPS + gh トークン(credential.helper='!gh auth git-credential')経由へ自動フォールバックして標準入力なしで実行する。

「fetch して」「pull して」「リモートの変更を取り込んで」「最新を取ってきて」と頼まれたが SSH 認証が使えない、fetch/pull が publickey で弾かれた、remote-control からリモートの更新を取り込みたい、といった場面で使う。gh-push の取り込み(incoming)版。

`/gh-fetch` で明示起動も可。GitHub(gh) 前提。

インストール方法を見る

含まれるファイル(3)

  • SKILL.md11.7 KB
  • scripts/gh-fetch.sh20.9 KB
  • scripts/tests/gh-fetch.test.sh7.5 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

gh-fetch — 非対話 fetch / pull(SSH 優先・gh フォールバック)

このスキルの目的

非対話セッション(TTY 無し)でリモートの変更を取り込む。経路は [[gh-push]] と同一方針で 決定論的に 選ぶ:

  1. SSH 優先 — remote が SSH URL で、かつ ssh -o BatchMode=yes による非対話 SSH 認証が実際に通るなら、素の git fetch を SSH で実行する。判定は agent の鍵有無ではなく BatchMode=yes での ls-remote が成功するかで直接テストする(agent の鍵・パスフレーズ無しのディスク鍵・macOS キーチェーン鍵を区別せず「非対話で通るか」を確かめられる)。GIT_SSH_COMMAND='ssh -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new' を強制し、パスフレーズ入力プロンプトや接続ハングに落ちず即失敗させる。

  2. gh(HTTPS) フォールバック — SSH fetch が失敗した場合、または SSH が使えない(HTTPS remote / 非対話 SSH 認証テストが失敗)場合は、通信認証を gh の credential helper に肩代わりさせて HTTPS で取得する:

    git -c credential.helper= -c credential.helper='!gh auth git-credential' fetch <https-url> +refs/heads/<branch>:refs/remotes/<remote>/<branch>
    

    credential.helper=(空)で既存ヘルパー一覧をリセットし gh ヘルパーだけを使う。remote が SSH URL でも URL を HTTPS に変換して取得元に使うので origin の設定は変更しない。public リポジトリならトークン無しでも HTTPS 変換だけで通る(gh helper は private のとき効く)。

「SSH で取得できるか」は ssh -o BatchMode=yes の ls-remote を1回打って直接テストすれば決定論的に判定できる。判定の ls-remote はリモート tip 取得と兼ねるので往復コストは増えない。非対話 SSH が通る環境(ssh-agent 常駐・macOS キーチェーン・パスフレーズ無しのディスク鍵など)では素の fetch がそのまま通るため、余計なトークン経由を挟まない。ssh-add -l(agent の鍵一覧)では、agent が空でもディスク鍵やキーチェーン鍵で非対話認証できるケースを取りこぼすため使わない。

判定の ls-remote は refs/heads/<branch> に限定する(refs/heads/* で全ブランチを引かない)。全一覧は使い道が無く、ブランチ数の多いリポジトリでは出力が数百KB に達して抽出処理を壊すため(後述の「異常終了の切り分け」参照)。

SSH 認証テストのメモ化: 非対話 SSH 認証の成否は host 単位で決まりリポジトリ/ブランチに依存しないため、セッション内で一度成功したら結果を /tmp/gh-ssh-authcache.<session_id>.<host> に記録し、以降の preflight / fetch / pull では実 ls-remote を省いて即 SSH 経路を採る(TTL 30 分・成功のみキャッシュ・セッション毎に独立)。キャッシュヒット時は tip を SSH で 1 ブランチ分だけ引く。実 fetch が成功すれば TTL を延長し、SSH が失敗(鍵失効等)すればキャッシュを破棄して gh 経路へ降格する。$CLAUDE_SESSION_ID が無い環境ではメモ化せず従来どおり毎回テストする。[[gh-push]] とキャッシュを共有する。

fetch と pull の違い(重要)

push と違い、取り込みは2段階で危険度が分かれる:

  • fetch … remote-tracking ref を更新し object を取得するだけ。作業ツリーを一切触らないので常に安全。
  • pull … fetch + 作業ブランチへの統合(merge/rebase)。作業ツリーを書き換える。未コミット変更との競合・コンフリクトが起きうる。

この性質差ゆえ、既定の統合戦略は --ff-only(fast-forward のみ) にしてある。最も多い「ローカルが clean でリモートに追従しているだけ」のケースをコンフリクト無しで取り込み、履歴が分岐している場合は作業ツリーを触らずに明示的に停止して戦略選択をユーザーに委ねる。これは gh-push が diverged で停止するのと同じ思想。

前提

  • SSH 経路の条件: remote が SSH URL(ssh://git@… または git@host:owner/repo)で、ssh -o BatchMode=yes の非対話 SSH 認証が実際に通ること(agent 鍵・パスフレーズ無しのディスク鍵・キーチェーン鍵のいずれでも可)。揃わなければ自動的に gh 経路になる。
  • gh 経路(フォールバック)の条件: private リポジトリの取得には gh auth status でログイン済み+トークンの read 権限が要る(public は gh 未認証でも HTTPS 変換だけで通る)。
  • SSH が使えず gh も未導入のときは preflight/fetch が ERROR: で停止する。SSH 鍵を非対話で使える状態にするか GitHub CLI を導入する。
  • GitHub(github.com / GitHub Enterprise)が対象。GitLab 等 gh が扱わないホストは gh 経路が使えない — SSH が通らなければ対象外(SSH 鍵や glab を案内する)。

ワークフロー

判定・URL 変換・状態算出・取り込み実行はすべて決定論的なので、git コマンドを手で並べ直さず scripts/gh-fetch.sh を使う。

1. preflight(取り込み対象を収集して提示)

bash <skill-dir>/scripts/gh-fetch.sh preflight [branch]

=== SECTION === 区切りの出力を読み、取得経路(SSH / gh)・取得元 URL・ブランチ・取り込まれるコミット・作業ツリーの状態をユーザーに提示する。TARGET の route 行で経路と理由、AUTH で非対話 SSH 認証テストの成否と gh 認証が分かる。STATE の incoming の意味:

  • up-to-date … リモート tip を既に保持。取り込み不要。
  • behind … ローカルがリモートの祖先。FF で安全に取り込める。取り込まれるコミット一覧が出る。
  • diverged … 履歴分岐。FF 不可。pull には --merge / --rebase が要る。ここで停止してユーザーに確認(rebase か merge か、そもそも取り込むか)。
  • fetchable … リモートに新規コミットがあるが未取得で件数不明。fetch すれば確定する。
  • missing-remote … リモートにそのブランチが無い。取り込むものがない。

WORKTREE セクションで dirty / clean を確認する。dirty のとき pull は実行できない(fetch は可)。preflight が ERROR: を出したら、その内容(非対話 SSH 認証不可 かつ gh 未導入・未対応 URL・detached HEAD 等)を解決してから進む。実行結果の OK: [ssh] / OK: [gh] でどちらの経路を使ったか分かる。

2. 実行

意図に応じて使い分ける:

fetch のみ(作業ツリーを触らず ref と object だけ更新したいとき。常に安全):

bash <skill-dir>/scripts/gh-fetch.sh fetch [branch]

実行後、未取り込みコミット件数と一覧を出す。

pull(作業ブランチへ統合まで行う):

bash <skill-dir>/scripts/gh-fetch.sh pull [branch]              # 既定 = --ff-only
bash <skill-dir>/scripts/gh-fetch.sh pull [branch] --merge      # ユーザー承認後のみ
bash <skill-dir>/scripts/gh-fetch.sh pull [branch] --rebase     # ユーザー承認後のみ

起動=取り込み意図とみなし、preflight 提示後そのまま実行してよい。ただし:

  • 作業ツリーが dirty なら pull は走らない(スクリプトが停止)。先に commit / stash をユーザーに促す。
  • diverged(FF 不可)で --merge/--rebase を付けるのは、必ずユーザー確認後。既定の --ff-only は分岐時に作業ツリーを触らず安全に失敗する。
  • 統合中にコンフリクトが出たら、スクリプトは中止せずコンフリクトファイルを提示して停止する。作業ツリーは統合途中の状態で残るので、ユーザーが解決(git rebase --continue / git commit)か中止(--abort)を選べる。

異常終了の切り分け

スクリプトが ERROR: 以外の形で落ちたとき(出力ゼロ + exit code が 0/1 以外)は、 サンドボックスや環境の制約と決めつけず、次の順で切り分ける。素の git fetch / git pull へ逃げてはいけない(経路判定・dirty 判定・--ff-only 既定を全て失う)。

  1. exit code と stdout/stderr を分けて取る。パイプ越しでは $? がスクリプトの 終了コードにならない。

    bash <skill-dir>/scripts/gh-fetch.sh preflight >/tmp/out 2>/tmp/err; echo "EXIT=$?"
    
  2. bash -x で最後に実行された行を見る。出力は大きいのでファイルへ落とし末尾だけ読む。

    bash -x <skill-dir>/scripts/gh-fetch.sh preflight >/dev/null 2>/tmp/trace; tail -5 /tmp/trace
    
  3. exit 141 は SIGPIPE(128+13)。set -o pipefail + set -e と組み合わさると、 パイプ上流が SIGPIPE を受けた時点でスクリプト全体が出力ゼロのまま即死する。 スクリプト冒頭を読んでも原因は見えないので、bash -x の最後の行を必ず見る。 スクリプト側の対処は「大きな出力を早期 exit するフィルタへパイプしない」 (scripts/gh-fetch.sh の first_sha はこのためにパイプを使わない)。

  4. 引数形式の疑いは --help では確かめられない(未知オプションとして ERROR: になる)。 本ファイルの「ワークフロー」節が唯一の仕様。

ERROR: で止まった場合は環境要因ではなくスクリプトの意図的な停止なので、 メッセージの指示(gh auth login / dirty / FF 不可 等)に従う。

制約

  • --merge / --rebase はユーザーの明示承認が無い限り付けない。既定は --ff-only、分岐検出時は停止が既定。
  • このスキルは取り込みが目的なので、起動された時点で fetch は実行してよい。pull で作業ツリーを書き換える前は、取り込まれる内容を提示した上で一言断る。
  • remote URL や対象ブランチが曖昧・複数候補ありうるときは、憶測で取り込まず確認する。

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

agent-teams

無料日本語概要

Claude Code の並列エージェント(agent teams・teammate)の後始末と無応答時の打ち切りルール。`name` を付けて Agent を起動するとき、TeamCreate でチームを組むとき、teammate から `idle_notification` が届いたとき、評価ループ等で次のイテレーションのエージェントを起動する前、エージェントの返信が届かないときに参照する。`name` を付けない通常のサブエージェント起動だけなら対象外。

yasunori0418/skills82026年10月12日 更新

basic-design

無料日本語概要

spec.md の REQ-# を入力に、機能一覧・モジュール構成・インターフェース・データフローを持つ docs/dev/<対象>/basic-design.md を作成・改訂するスキル。/basic-design <対象名> で明示的に呼び出されたときのみ使用する。

yasunori0418/skills82026年10月12日 更新

biz-translate

無料日本語概要

技術的な内容を、技術用語を排したビジネス職向けの平易な説明文に翻訳する。`/biz-translate` と明示的に呼ばれたときのみ実行する。

yasunori0418/skills82026年10月12日 更新

commit-flow

無料日本語概要

`git commit` / `git commit --amend` を実行する前、または「commit」「amend」「コミット」「コミットして」の一語・短文だけを渡された時点で必ず発火する git コミット実施ルール。理由や差分の説明が一切無くても、ファイル全文を読んでメッセージを組み立てる前に先に参照する。主目的は論理的に独立した修正を都度・適切な粒度でコミットすること。メッセージは Conventional Commits 形式、素材は同梱の決定論スクリプト commit-context.sh が出す staged diff のみ。「コミット分けて」と依頼される、独立した複数修正をまとめるか分けるか判断する、レビューコメント対応をコミットする、rebase / squash / cherry-pick 後のメッセージを整える、`gh pr create` の PR タイトルをコミット流儀へ揃える場面でも参照する。plan モードでのコミット計画の立案は commit-plan スキルの領分。

yasunori0418/skills82026年10月12日 更新

commit-plan

無料日本語概要

実装計画・リファクタリング計画・レビュー対応計画・並列作業のタスク分解など、計画を成果物として書き出すときに必ず参照するコミット計画ルール。plan モードでは ExitPlanMode で plan を提示する前に必須、計画ドキュメントや job-graph のタスク分解・エージェントへの指示文でも同様に適用する。計画成果物にコミット計画セクション(論理的に独立した修正単位での分割と Conventional Commits 形式のメッセージ)が無ければ実装に入らない。「実装計画を立てて」「planを立てて」「実行計画を作って」「リファクタリング計画を立てて」「コミット計画を立てて」「タスクを分解して」と依頼される、複数の独立した修正をまとめるか分けるか計画段階で判断する等の場面では、ユーザーが「コミット」に一切言及していなくても必ず発火する。コミットの実施(素材収集・メッセージ確定・git commit 実行)は commit-flow スキルが担う。

yasunori0418/skills82026年10月12日 更新

def-done

無料日本語概要

プロジェクトに 1 つの「完成の定義」docs/dev/definition-of-done.md を対話で構築・改訂し、機械判定節と人判定節の二部構成で書き出すスキル。/def-done で明示的に呼び出されたときのみ使用する。

yasunori0418/skills82026年10月12日 更新

yasunori0418 のスキルをすべて見る

このスキルの問題を報告する