シャロークローンからプッシュ時の「fatal: shallow update not allowed」を修正する

intermediate📦 Git2026-06-19| Linux、macOS、Windows上のGit 2.x — --depthフラグを使用したシャロークローンのCI/CDパイプライン(GitHub Actions、GitLab CI、Jenkins、CircleCI)で発生しやすい

Error Message

fatal: shallow update not allowed
#git#シャロークローン#プッシュ#アンシャロー#ci-cd

エラーの内容

深さフラグを指定してクローンした後、git push が失敗します:

fatal: shallow update not allowed

このエラーはリリース手順の中で最もよく発生します。CIランナーが帯域幅を節約するためにシャロークローンを取得し、その後のジョブがタグ、バージョンバンプ、またはビルドアーティファクトブランチをプッシュしようとすると、Gitが完全に拒否します。

原因

シャロークローンは意図的に不完全な状態になっています。Gitは .git/shallow というファイルでカットオフポイントを管理しており、そこには親がダウンロードされなかった境界コミットが列挙されています。

リモートがプッシュを受け取ると、コミットの祖先をたどってすべてが正しく繋がっているか検証します。リモートが認識していない境界に到達すると、履歴グラフが壊れるリスクを避けるために処理を中断します。以下の3つの状況でこのエラーが発生します:

  • ローカルで git clone --depth N を使用し、完全なリモートにプッシュしようとしている。
  • CIランナーが fetch-depth: 1actions/checkout のデフォルト)でチェックアウトし、後のステップでタグやコミットをプッシュしようとしている。
  • シャロークローンから別のシャロークローンにプッシュしようとしている — 両側とも履歴が不完全で、どちらも不足分を補えない。

まず診断する

以下のコマンド一つで、リポジトリがシャローかどうか確認できます:

git rev-parse --is-shallow-repository

true であればシャロークローンです。境界を直接確認することもできます:

cat .git/shallow

このファイルが存在して内容があれば、シャロークローンの状態です。各行はダウンロードされた範囲の端を示すコミットSHAです。

修正方法1 — プッシュ前にアンシャロー化する(推奨)

完全な履歴をフェッチしてからプッシュします:

git fetch --unshallow
git push origin HEAD

これにより不足しているすべてのコミットが取得され、.git/shallow が削除されて完全なクローンに変換されます。以降はプッシュが正常に動作し、追加の回避策は不要です。

--unshallow が使えない古いGitバージョンの場合は、代わりにこちらを使用します:

git fetch --depth=2147483647
git push origin HEAD

2147483647 は INT_MAX の値です。Gitはこれを「すべて取得する」と解釈し、同じ結果が得られます。

修正方法2 — CIのチェックアウト深さを変更する

CIパイプラインの場合、より良い解決策はプッシュを行うジョブでシャロークローンを使わないことです。深さ0はリリースとデプロイのジョブのみに設定し、テストとlintのジョブはシャローのままにできます。

GitHub Actions

- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # 0 = 完全な履歴

GitLab CI

variables:
  GIT_DEPTH: 0

Jenkins(パイプラインスクリプト)

checkout([
  $class: 'GitSCM',
  extensions: [[$class: 'CloneOption', shallow: false]],
  // ... その他のオプション
])

修正方法3 — タグのみを対象とした限定フェッチ

単一のタグをプッシュしたいが、大量の履歴をダウンロードしたくない場合は、タグのコミットに必要な分だけフェッチします:

git fetch --depth=1 origin main
git tag v1.2.3
git push origin v1.2.3

これはタグがリモートにすでに存在するコミットを指している場合にのみ有効です。リモートが認識していない新しいコミットをプッシュする場合は、修正方法1または修正方法2に戻ってください。

修正方法4 — リモートリポジトリ自体がシャローの場合

まれなケースですが、誰かが git clone --depth N --bare でベアリポジトリを作成した場合に発生します。その場合は、サーバー側でアンシャロー化します:

# サーバー上で実行
cd /path/to/remote.git
git fetch --unshallow

サーバーにアクセスできない場合は、完全なクローンからリモートを再作成してください。

修正を確認する

リポジトリがシャローでなくなったことを確認します:

git rev-parse --is-shallow-repository
# Should print: false

その後、プッシュを再試行します:

git push origin HEAD
# タグの場合:
git push origin v1.2.3

fatal: が出力されなければ成功です。

CI/CDでの予防策

シャロークローンが存在する理由は一つ、速度です。50,000コミットのリポジトリでdepth 1のクローンを使うと、チェックアウト時間を30秒から2秒以下に短縮できます。このトレードオフは、履歴を参照しないコンパイルやテストのジョブには有効です。

ただし、過去の履歴を参照する必要があるジョブ — コミットのプッシュ、タグの作成、git describe の実行、チェンジログの生成、リリース間の差分確認 — では、このトレードオフが問題を引き起こします。

実用的な使い分け:テストとlintには fetch-depth: 1、リリースとデプロイには fetch-depth: 0 を設定します。ほとんどのCIシステムではジョブごとに設定できるため、速度が重要な場所では速度を、正確性が求められる場所では正確性を確保できます。

ジョブ数が多いパイプラインでは、完全な履歴をフェッチして .git ディレクトリをキャッシュする専用チェックアウトジョブの作成を検討してください。後続のジョブはキャッシュから復元することで、再クローンを避けられます。

クイックリファレンス

  • ローカルのシャロークローン → 通常のリモート: git fetch --unshallow && git push
  • depth: 1 のCIパイプライン: チェックアウトステップで fetch-depth: 0 を設定する
  • タグのみをプッシュする場合: git fetch --depth=1 origin <branch> && git push origin <tag>
  • リモートがシャローの場合: リモートをアンシャロー化するか再作成する

Related Error Notes