GitHub

actions/checkoutとは|v7の既定変更・主要入力と浅いクローンの壊れ方

actions/checkoutとは|v7の既定変更・主要入力と浅いクローンの壊れ方

actions/checkoutは、ワークフローの実行環境にリポジトリの中身を取り出すアクションです。1行置けば動くので既定値のまま放置されやすいのですが、その既定は「トリガーになった1コミットだけ」の浅いクローンで、タグや履歴を前提にした処理はそこで静かに壊れます。さらに2026年6月公開のv7で、pull_request_targetとworkflow_runからフォークのコードを取り出す動作が既定で拒否され、同年7月20日からは古いメジャー版にも同じ制限が入りました。本記事では主要な入力の既定値、履歴不足で失敗する処理の直し方、v7の遮断への移行判断までを、そのまま貼って動かせるワークフロー例とともに扱います。既定値と版の記述は公式リポジトリ actions/checkoutの内容を2026年9月時点で確認したものです。GitHub Actionsそのものの構造や書き方はGitHub Actionsの基本構造とワークフローの書き方を解説した記事に譲ります。

まとめ:actions/checkoutで先に決める入力4つとv7移行の順序

触るべき入力は多くありません。決めるのは、履歴をどこまで取るか(fetch-depthとfetch-tags、あるいはfilter)、資格情報を後続ステップに残すか(persist-credentials)、サブモジュールや別リポジトリを含めるか(submodulesとrepository)、フォークのプルリクエストを扱う経路があるか(allow-unsafe-pr-checkout)の4点です。残りは既定のままで大半のワークフローが成立します。

先に判定すべきはv7への更新可否です。v7と、2026年7月20日公開のv2.8.0からv6.1.0までのバックポート版は、pull_request_targetとworkflow_runでフォークのコードを取得しようとすると失敗します。履歴の取り方は「まずfetch-tags、足りなければfilter、fetch-depth 0は最後」の順です。全履歴の取得はクローン時間に直結し、課金対象の実行時間として跳ね返ります。

最小のcheckoutステップを書いて内部のgit処理を確認する手順

中身を知っておくと失敗ログの読み方が変わります。実行される処理の順序から押さえます。

init・fetch・checkoutの3段階とGit 2.18未満の退避動作

処理は大きく3段階です。$GITHUB_WORKSPACEの直下に作業ディレクトリを用意して初期化し、認証情報を設定したうえで対象のrefだけをfetchし、最後にそのrefへcheckoutします。ジョブ終了後にはpost処理が走り、設定した資格情報を取り除きます。

ランナーのPATHにGit 2.18以上が無い場合、アクションはgitを使わずREST API経由でファイルをダウンロードする経路へ退避します。この退避が起きるとリポジトリとしてのメタデータが揃わず、ジョブの後半でgitコマンドを叩く処理は動きません。スリムなイメージのセルフホストランナーで「gitが見つからない」系の失敗が出たら、Gitの版を疑ってください。

clean既定trueがfetch前に消す未コミットの生成物と対処

見落としやすいのがcleanで、既定はtrueです。fetchの前に作業ツリーの掃除とHEADへのリセットが走ります。GitHubホステッドランナーは毎回まっさらな環境なので影響しません。話が変わるのは、ワークスペースを再利用するセルフホストランナーです。checkoutより前のステップで書き出した設定ファイルは、この掃除で消えます。clean: falseにするか、checkoutを最初のステップへ固定してください。

ref・repository・tokenの既定値とoutputsで取れるcommit

repositoryの既定はワークフローが動いているリポジトリ自身、tokenの既定はそのジョブのGITHUB_TOKEN、refを省略した場合はイベントが指すrefかSHAです。

プルリクエストのトリガーで取り出されるのは、マージ先を試したdetached HEADです。ブランチはチェックアウトされていません。生成物をそのPRブランチへ押し戻すなら、refにgithub.head_refを渡し、permissionsへcontents: writeを与えます。実際に取り出されたrefとコミットはoutputsのrefとcommitで受け取れるため、ログのSHAを正規表現で切り出す処理は差し替えられます。

action.ymlで入力の既定値を読んで最小のステップを書く

入力の既定値は解説記事ではなく、公式リポジトリのaction.ymlを直接読むのが早道です。2026年9月時点のmainブランチでは、fetch-depthが1、fetch-tagsがfalse、cleanがtrue、persist-credentialsがtrue、submodulesがfalse、sparse-checkout-cone-modeがtrue、set-safe-directoryがtrue、ssh-strictがtrue、allow-unsafe-pr-checkoutがfalse、filterとsparse-checkoutは未設定(null)と書かれています。outputsに並ぶのはrefとcommitの2つだけです。

最小の構成は次の形です。fetch-depthは既定の1のままにして、タグだけをfetch-tagsで取りに行きます。これでgit describeがCIだけ落ちる事故は消えます。

steps:
  - uses: actions/checkout@v7
    with:
      fetch-depth: 1
      fetch-tags: true
  - run: git describe --tags --abbrev=0

入力を足す前に、その値がaction.ymlの既定と違うかを確かめてください。既定と同じ値を書き並べたwithブロックは、後から読む人に「ここは意図して変えた」と誤解させます。差分だけを書いたワークフローのほうが、版が上がって既定が動いたときに気づけます。

fetch-depthとfilterを設定して履歴不足の失敗を直す手順

不具合の相談で最も多い領域です。既定値が速さ優先に振られ、履歴を要する処理と噛み合いません。

fetch-depth既定1で失敗するgit describeとタグ取得の直し方

fetch-depthの既定は1で、fetch-tagsの既定はfalseです。手元にはコミットが1つあるだけで、タグは1本も来ていません。この状態でgit describe --tagsを呼ぶと、直近のタグが見つからず失敗します。タグからバージョン番号を組み立てるビルドスクリプトが、ローカルでは通るのにCIだけ落ちる典型がこれです。

直し方は2通りあります。タグだけが要るならfetch-tags: trueを足してください。fetch-depthが1のままでもタグを取りに行くため、履歴を全部引く必要はありません。注釈付きタグの扱いはv6.0.2で修正が入り、注釈を保ったまま取得されます。過去のコミットも辿るなら深さを数字で指定し、直前のコミットだけならfetch-depth: 2で足ります。

差分ビルドでベースブランチが見つからない原因と取得深さの決め方

モノレポで「変更されたディレクトリだけビルドする」構成を組むと、ベースブランチとの共通祖先が必要になります。浅いクローンでは共通祖先まで履歴が届かず、diffコマンドがunknown revisionで止まります。

安易にfetch-depthを0にする前に、比較対象を確認してください。比較先がベースブランチなら、その分岐点までの深さで足ります。ただし分岐点の位置は開発の進み方で動くため、固定値で当て続ける運用は持ちません。短命ブランチを高頻度でマージするチームなら数十コミット分で安定しますが、長寿命ブランチを抱えるなら次項のfilterへ寄せる方が確実です。そもそもパスによるジョブの起動制御はon直下のイベント選定とpathsフィルタの設計で切り分けられます。

fetch-depth 0の代わりにfilterで部分クローンする条件と実行時間

fetch-depthに0を渡すと全ブランチの全履歴を取得します。確実ではあるものの、履歴の長いリポジトリでは取得だけで数分かかり、その時間はランナーの課金対象です。分単価と無料枠はGitHub Actionsの分単価と無料枠を整理した記事で確認できます。

代わりに使えるのがfilterです。blob:noneを渡すと、コミットとツリーの構造だけを先に取り、ファイルの中身は必要になった時点で取り寄せる部分クローンになります。この仕組みはGit本体の機能で、フィルタの種類と制約はGit公式のpartial cloneドキュメントに記載されたとおりです。共通祖先の探索やコミットの列挙は構造だけで完結するため、差分検出やリリースノート生成はこれで通ります。

実際の書き方は次のとおりです。fetch-depthに0を渡していますが、ファイルの中身は遅延取得になるため、素の全履歴クローンより短く済みます。

steps:
  - uses: actions/checkout@v7
    with:
      filter: blob:none
      fetch-depth: 0
  - name: changed paths
    run: |
      base=$(git merge-base origin/main HEAD)
      git diff --name-only "$base" HEAD

逆に全ファイルを走査する静的解析では、遅延取得が何度も走って全履歴クローンより遅くなることもある形です。「履歴の形だけ要るのか、中身も要るのか」で決めてください。取得したあとの依存キャッシュ側の設計はGitHub Actionsのキャッシュ|actions/cacheのkey設計と復元されない原因の切り分けで扱っています。

persist-credentialsとtokenを設定して権限を絞り込む手順

資格情報まわりはv6で保存方式が変わりました。どこに何が書かれるかを先に把握します。

v6で保存先が変わった資格情報とgit configを読む処理の破損

persist-credentialsの既定はtrueです。v5までは認証ヘッダがリポジトリのローカルなgit設定ファイルへ直接書き込まれていました。2025年11月公開のv6からは$RUNNER_TEMP配下の別ファイルへ保存され、設定ファイル側からは参照される形に変わっています。

ワークフローの書き換えは不要で、fetchやpushはそのまま通ります。壊れるのは、設定ファイルを直接読んでトークンを取り出していた自前スクリプトです。認証ヘッダをgrepして流用していた場合、v6では値が見つかりません。もう1点、Dockerコンテナアクションから認証済みのgitを実行する構成は、ランナーがv2.329.0以降でないと動きません。

persist-credentials falseに倒す判断とtokenの権限設定

既定のtrueで問題になるのは、ジョブの後半で信頼できないコードを走らせる場合です。取得した資格情報はジョブが終わるまで残り、post処理で除去されます。その間に動くステップは、原理的にそのトークンを使えてしまう形です。

falseへ倒す判断基準は2つです。ワークスペースをそのままアーティファクトとして外へ出す構成であること。もう1つは、依存パッケージのビルドスクリプトなど、レビューしていないコードをジョブ内で実行すること。どちらにも当てはまらなければ既定のままで構いません。

あわせてpermissionsを絞ります。取得しかしないジョブはcontents: readで十分です。シークレットを渡す側の作法はGitHub Docsのシークレット利用ガイドに条件付きで整理されています。スコープの一覧と絞り込みの手順はGitHub Actionsのpermissions|GITHUB_TOKENの既定権限と最小権限の設計にまとめました。シークレットの渡し方はenv・vars・secretsの使い分けと受け渡しの記事にまとめました。

他リポジトリのチェックアウトでGITHUB_TOKENが届かない範囲

repositoryに別のリポジトリ名を渡せば、ツールや共通設定を置いたリポジトリを同じジョブへ取り込めます。ただし既定のGITHUB_TOKENの権限は、ワークフローが動いているリポジトリの範囲までです。

相手がパブリックなら既定のトークンでも取得できますが、プライベートまたはインターナルのリポジトリは認証で弾かれます。この場合はtokenに別の資格情報を明示してください。選択肢はデプロイキーによるSSH、細粒度のパーソナルアクセストークン、GitHub Appのインストールトークンの3つです。パーソナルアクセストークンは発行者個人に紐づくため、担当者の退職でワークフローが止まります。

2本目以降にはpathを付けて置き場所を分け、静的解析の対象へ混ざらないようにします。書くとこうなります。

steps:
  - uses: actions/checkout@v7
  - uses: actions/checkout@v7
    with:
      repository: my-org/shared-tools
      path: .tools
      token: ${{ secrets.TOOLS_TOKEN }}
      persist-credentials: false

submodulesとsparse-checkoutでモノレポの取得範囲を絞る手順

取得する範囲を絞る、あるいは広げる入力です。組み合わせたときの優先順位に癖があります。

submodules trueとrecursiveの差とSSH URLの自動変換

submodulesの既定はfalseで、サブモジュールのディレクトリは空のまま置かれます。trueを渡すと1階層分、recursiveなら入れ子のサブモジュールまで辿る設定です。ビルドがサブモジュール内のヘッダやライブラリに依存していると、指定しない限りコンパイルの段階で落ちます。

もう1つ知っておきたいのが、ssh-keyを渡していない場合の挙動です。参照先がSSH形式のURLで書かれていても、アクションはHTTPSへ書き換えて取得しに行きます。同じ組織内のパブリックなサブモジュールなら、これで通ります。プライベートなら、SSHの鍵を渡すかHTTPSで通るトークンをtokenへ指定してください。

sparse-checkoutのcone-mode既定とfilter併用時の優先順位

sparse-checkoutには取り出したいパスを改行区切りで並べます。巨大なモノレポで特定サービスのディレクトリだけをビルドするジョブなら、作業ツリーの展開量が減るぶん取得が短くなります。

steps:
  - uses: actions/checkout@v7
    with:
      sparse-checkout: |
        services/api
        libs/common

sparse-checkout-cone-modeの既定はtrueで、ディレクトリ単位の指定として解釈されます。ファイル名のパターンで絞る場合だけfalseにしますが、書き方が変わるうえ挙動も読みにくくなるため、まずはcone modeのままディレクトリで指定してください。注意点は優先順位です。action.ymlのfilterの説明には、この入力がsparse-checkoutを上書きすると明記されています。両方書いて絞り込みが効かないという相談は、仕様どおりの動きです。

v7で遮断されたpull_request_targetのワークフローを移行する手順

2026年に入って最大の変更がここです。既存のワークフローがそのまま失敗します。

v7と2026年7月のバックポートで拒否されるフォークPRの取得

2026年6月18日公開のv7.0.0で、pull_request_targetとworkflow_runをトリガーとするワークフローが、フォークのプルリクエストのコードを取り出す動作を既定で拒否するようになりました。この2つのトリガーは、ベースリポジトリのGITHUB_TOKEN、シークレット、既定ブランチのキャッシュ範囲、ランナーへのアクセスを持った状態で動きます。トリガーごとの権限差はGitHub Docsのイベント一覧で確認できます。そこへ外部から送られたコードを取り込んで実行する構成が、いわゆるpwn requestと呼ばれる攻撃経路です。

拒否される条件はGitHubのChangelogに列挙されています。フォーク由来のプルリクエストで、repositoryがフォーク側に解決される場合、refがrefs/pull/番号/headまたはrefs/pull/番号/mergeに一致する場合、refがフォークのheadかマージコミットのSHAへ解決される場合です。裏を返せば、ベースリポジトリの既定ブランチだけを取り出す使い方は今までどおり通ります。

制限はv7だけの話ではありません。Changelogでは施行日が当初2026年7月16日と告知され、その後7月20日へ変更されました。公式のリリース一覧を見ると、同日付でv6.1.0・v5.1.0・v4.4.0・v3.7.0・v2.8.0が並び、いずれにも同じ遮断とオプトイン入力が入っています。除外されたのはv1だけで、「v4で止めているから関係ない」という判断は成り立ちません。

pull_requestとworkflow_runへジョブを分割して移行する

遮断を受けたワークフローの移行先は、権限を持たない側でコードを動かし、権限が要る処理だけを別のワークフローで受け取る形です。前半はpull_requestで起動し、フォークのコードをそのままチェックアウトします。このトリガーではシークレットが渡らず、GITHUB_TOKENも読み取りに落ちるため、遮断の対象になりません。

name: pr-build
on:
  pull_request:
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - run: npm ci
      - run: npm test --if-present
      - uses: actions/upload-artifact@v4
        with:
          name: pr-result
          path: dist

後半はworkflow_runで受け、結果のアーティファクトだけを読みます。ここではcheckoutを書きません。書かなければ遮断にも当たらず、フォークのコードがシークレット付きの環境へ入る経路そのものが消えます。

name: pr-report
on:
  workflow_run:
    workflows: [pr-build]
    types: [completed]
permissions:
  pull-requests: write
jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: pr-result
          run-id: ${{ github.event.workflow_run.id }}
          github-token: ${{ secrets.GITHUB_TOKEN }}
      - run: cat dist/summary.txt

この形に組み替えると、allow-unsafe-pr-checkoutを立てずに済みます。移行の手間は2本のワークフローを行き来するぶん増えますが、遮断が入るたびに例外を足していく運用よりは寿命が長いものです。

allow-unsafe-pr-checkoutを立てる前に検討する2つの回避策

遮断を解除する入力がallow-unsafe-pr-checkoutで、action.ymlの既定はfalseです。trueにすれば従来どおり動きますが、これはリスクを引き受ける宣言であって、移行作業の代わりにはなりません。Changelog側にも、コードレビューで目に留まるよう意図してこの名前にしたと書かれています。

先に検討すべき回避策は2つあります。1つ目は、フォークのコードを実行する必要が本当にあるかの見直しです。ラベル付け、コメント投稿、サイズ判定はメタデータだけで完結し、コードの取得自体が要りません。この場合はcheckoutのステップごと外します。2つ目が前項のジョブ分割です。ビルドとテストは権限を持たないpull_requestのワークフローで走らせて結果をアーティファクトへ残し、シークレットが必要な処理だけをworkflow_run側で受け取ります。

pull_request_targetを残す場合のジョブ分割とラベル運用の条件

それでも特権付きの経路でフォークのコードを動かす場面は残ります。外部コントリビューターのPRへ、有料APIの鍵を使う結合テストを流す構成です。踏むべき順序は次のとおりです。

  1. メンテナが内容を確認し、承認を示すラベルを付ける
  2. そのラベル付与イベントだけを起動条件にする
  3. ジョブをEnvironmentに紐づけ、承認者を必須にする
  4. 取得するrefをPRのheadのコミットSHAで固定する
  5. allow-unsafe-pr-checkoutをtrueにし、permissionsを読み取りへ絞る

refをブランチ名ではなくコミットSHAで固定するのは、確認した時点のコードと実行されるコードを一致させるためです。ブランチ名のままだと、承認後に押し込まれたコミットが特権付きで走り、ラベル運用は意味を失います。この5段を運用できないチームは、allow-unsafe-pr-checkoutをtrueにせず、外部PRの結合テストを手元で回してください。

v4からv7を選び分けてランナー要件とSHA固定を設定する手順

版の選び方は「新しい方がよい」で終わらせず、ランナーの版と固定方針まで含めて決めます。

v4・v5・v6・v7の変更点とランナー最小バージョンの対応表

各メジャー版の違いは次のとおりです。ランナーの要件は、セルフホストランナーを使っている場合にだけ効きます。ラベルそのものの書き方とランナーの選び分けはGitHub Actionsのruns-on|ラベル指定の記法と-latest更新・arm64への備えで扱っています。

版 主な変更 ランナーの最小要件
v4系 2026年7月に遮断を後追い 明示なし
v5系 node24ランタイムへ更新 v2.327.1以上
v6系 資格情報を別ファイルへ保存 Docker実行はv2.329.0
v7系 フォークPRを既定で遮断 v2.327.1以上

GitHubホステッドランナーだけを使うなら、素直にv7を選びます。セルフホストランナーやGitHub Enterprise Serverで古いランナーを動かしているなら、v5以降がnode24を要求する点が効きます。上げられない期間はv4系に留め、その版でも遮断は効いている前提で移行を進めてください。

リリースノートとChangelogで既定の変更を追う運用手順

既定値の変更は、手元のワークフローを書き換えなくても挙動を動かします。変更を追うための確認先は、次の2つで十分です。1つはリリース一覧で、v7.0.1が2026年7月20日、v7.0.0が同年6月18日、v6.0.3が6月2日、v6.0.2が1月9日という具合に、日付と変更点が並びます。もう1つがGitHubのChangelogで、こちらには施行日の変更のような運用側の告知が載ります。7月16日から7月20日への延期はリリースノートではなくChangelog側で読めました。

実務では、四半期に一度この2つを眺める時間を取り、BREAKINGの表示が付いた版だけを拾えば足ります。CI基盤を担当する人が変わっても回るよう、確認先のURLと頻度を運用ドキュメントへ書いておいてください。バージョン更新の自動化を入れている場合でも、既定値の変更は差分に現れないため、人が読む工程は残ります。

コミットSHAで固定した場合に届かない既定変更と追随の運用手順

サプライチェーン対策としてアクションをコミットSHAで固定する方針自体は妥当です。手法の詳細はGitHub ActionsのコミットSHA固定とEnforce設定の解説にまとめてあります。

ただし固定には副作用があります。2026年7月20日のバックポートのような、既定値を安全側へ寄せる変更が自動では届きません。タグ参照なら意識せず新しい既定に乗りますが、SHA固定では明示的に更新するまで古い挙動のままです。固定を採るなら、依存更新の自動化を同時に入れ、月次でSHAを引き上げる運用まで設計してください。固定だけ導入して更新の仕組みを持たない状態が、いちばん危うい形です。

fetch-depth 0を既定にしない判断と自作cloneを見送る理由

ここは言い切ります。fetch-depth 0を全ワークフローの標準にするのは避けてください。全履歴が要るのは、タグからバージョンを生成する処理、リリースノートを履歴から組み立てる処理、履歴全体を読む静的解析の3つだけです。ほかのジョブで0を指定すると、取得時間ぶんの実行時間を毎回支払い続けます。

もう1つ見送るべき選択が、checkoutを使わず自前のgit cloneステップへ置き換える構成です。認証情報の埋め込みは自分で書けますが、ジョブ終了時にそれを取り除くpost処理がありません。ワークスペースを再利用するセルフホストランナーでは、資格情報が残り続けます。細かい制御が要るなら、persist-credentialsをfalseにしたうえで必要なgit操作だけ後続ステップへ足してください。取得工程の設計から運用の引き取りまで外部に任せたい場合は保守運用・内製化支援のサービスが受け皿になり、前提となるパイプラインの考え方はCI/CDの仕組みと導入判断を整理した記事で確認できます。

よくある質問

設定で相談が多い点をまとめます。

actions/checkoutを書かないとどうなりますか?

実行環境は空のディレクトリから始まるため、リポジトリのファイルは1つも存在しません。ビルドやテストのコマンドは対象が見つからずに落ちます。GitHub APIを叩くだけ、イシューにコメントするだけといった中身を読まないジョブなら省略でき、クローンの時間ぶん実行が短くなります。

fetch-depthは0にしておけばよいですか?

常用は勧めません。0は全ブランチの全履歴を取得するため、履歴の長いリポジトリでは取得だけで数分かかり、その時間が毎回の課金対象になります。タグだけが要るならfetch-tagsをtrue、共通祖先の探索が要るならfilterにblob:noneを渡す部分クローンで足ります。中身まで必要な処理だけ0を指定してください。

persist-credentialsをfalseにするのはどんなときですか?

ジョブの後半でレビューしていないコードを実行する場合と、ワークスペースをそのままアーティファクトとして外へ出す場合の2つです。既定のtrueでは資格情報がジョブ終了まで残り、その間に走るステップは原理的にそれを使えます。自分たちのテストとビルドを回すだけなら既定で構いません。

pull_request_targetでフォークのコードが取得できなくなったのはなぜですか?

2026年6月18日公開のv7.0.0で、pull_request_targetとworkflow_runからフォークのコードを取り出す動作が既定で拒否されるようになったためです。これらのトリガーはベースリポジトリのシークレットとトークンを持って動くため、外部のコードを実行すると権限ごと乗っ取られます。同年7月20日にはv2.8.0からv6.1.0までへ同じ制限がバックポートされました。解除はallow-unsafe-pr-checkoutで可能です。

別のプライベートリポジトリをチェックアウトするには何が必要ですか?

repositoryに対象のリポジトリ名、pathに配置先を指定したうえで、tokenへ別の資格情報を渡します。既定のGITHUB_TOKENは自リポジトリの範囲までしか権限を持たず、そのままでは認証で弾かれます。候補はデプロイキー、細粒度のパーソナルアクセストークン、GitHub Appのインストールトークンの3つで、組織運用ならGitHub Appのトークンが引き継ぎで詰まりません。

関連記事

お気に入りに入れた記事の一覧

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.09 テックブログ IDCFクラウド(IDCフロンティア)不正アクセス・ランサムウェア:影響先・復旧・データは戻るか
  2. 2026.10.08 テックブログ 大阪公立大学のランサムウェア被害と仮想化基盤の停止|全授業休講に至った経緯とバックアップを守る設定
  3. 2024.11.08 テックブログ OpenAPI GeneratorでJavaコードを自動生成する方法|CLI導入からSpring・ライブラリ選択まで
  4. 2026.10.09 テックブログ ニッスイのサイバー攻撃で日水物流の入出荷停止|委託先クラウド障害に荷主が備える手順
  5. 2026.10.09 テックブログ 京王電鉄のランサムウェア被害とグループ共通基盤:決済・ポイント・予約が止まった範囲と遮断の初動

RELATED POSTS 関連記事

目次