はじめに
Claude Code、Cursor、Copilot — AIにコードを書かせる時代になりました。
そしてその流れで、コード以外もGitHubに置く人が増えています。
- AIエージェントの設定ファイル・記憶データ
- 会社のナレッジベース
- 契約書・請求書
- 確定申告の書類(PDF・画像)
「AIに自分の情報を持たせたい」「どのPCからでもアクセスしたい」「バージョン管理したい」— 理由は正しいです。GitHubは最適な選択肢でしょう。
ただし、HTTPS接続のままだと、あるタイミングで詰みます。
それは、会社の情報、契約書、確定申告の書類…… PDFや画像をコツコツ積み重ねていって、リポジトリに情報が十分に集まった瞬間です。まさにAIに読ませて活用したい、そのタイミングでgit pullが通らなくなります。
私の場合、業務ドキュメント(PDF・画像約110ファイル、計35MB)をGitHubにpushした後、別PCでgit pullしたら通信が途中で死にました。cloneすらできなくなりました。
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
fatal: early EOF
fatal: fetch-pack: invalid index-pack output
この記事では、なぜHTTPS接続が壊れるのか、そしてなぜSSH接続一択なのかを解説します。
何が起きたか
環境
- Ubuntu 22.04(WSL2)
- Git 2.34.1(GnuTLS版)
- リポジトリ: PDF・JPG・PNG・XLSX 約110ファイル、35MB
症状
$ git pull
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
error: 6742 bytes of body are still expected
fetch-pack: unexpected disconnect while reading sideband packet
fatal: early EOF
fatal: fetch-pack: invalid index-pack output
git clone --depth 1 でもダメでした。リポジトリに触れなくなりました。
なぜHTTPS接続は壊れるのか
通信の仕組みを理解する
git clone https://... を実行すると、内部では以下が起きています:
git clone (HTTPS)
└→ git-remote-https(HTTPSクライアント)
└→ libcurl(HTTP通信ライブラリ)
└→ libgnutls(SSL/TLS暗号化) ← ここが壊れる
└→ TCP接続 → GitHub
Ubuntu標準のGitは、HTTPS通信にGnuTLSというSSL/TLSライブラリを使っています。
$ ldd /usr/lib/git-core/git-remote-https | grep tls
libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30
GnuTLSの何が問題なのか
GnuTLSには大容量データの受信中にTLSセッションが切断される既知の問題があります(Stack Overflow、Ask Ubuntu)。
具体的には以下の3点です:
- TLSレコードサイズの制限 — GnuTLSはTLSレコードの処理中にバッファが溢れると、セッション全体を切断します。OpenSSLはこの状況で再試行しますが、GnuTLSはしません
- HTTP/1.1のチャンク転送との相性 — Gitのpackファイル転送はHTTP chunked encodingを使います。大きなpackファイル(バイナリ多数)だとチャンクが巨大になり、GnuTLSのTLS処理が追いつきません
- 再接続ロジックの欠如 — 一度TLSセッションが切れると、libcurl側でリトライしてもGnuTLS側が復帰できません
テキストファイル(ソースコード)だけなら問題になりません。packファイルが小さいからです。しかしPDF・画像・バイナリファイルが入った瞬間にpackファイルが肥大化し、GnuTLSの限界に達します。
なぜオプション設定しても直らないのか
| 対策 | コマンド | なぜ効かないか |
|---|---|---|
| HTTPバッファ拡大 | git config --global http.postBuffer 524288000 |
postBufferはpush時の送信バッファです。受信側(fetch/clone)のGnuTLS問題には無関係です |
| タイムアウト緩和 | git config --global http.lowSpeedLimit 0 |
タイムアウトではなくTLSセッション自体が異常切断されています。待ち時間の問題ではありません |
| 浅いクローン | git clone --depth 1 |
コミット履歴は減りますが、最新コミットのpackファイル自体が大きいので転送量はほぼ変わりません |
| Swap追加 | sudo fallocate -l 2G /swapfile |
メモリ不足ではなくTLS通信層の問題です。メモリを増やしても通信は安定しません |
全部ダメでした。 これらのオプションはGit層やOS層の設定であり、GnuTLSのTLS処理層には届きません。問題のレイヤーが違うのです。
[Git設定] ← postBuffer、lowSpeedLimit(ここをいくら弄っても)
↓
[libcurl] ← HTTP通信(ここも正常)
↓
[GnuTLS] ← TLSセッション切断(★ここが壊れてる)
↓
[TCP/IP] ← ネットワーク自体は正常
なぜSSH接続だと解決するのか
SSH接続はHTTPS/GnuTLSを一切通りません。完全に別の通信経路です。
git clone (SSH)
└→ git-remote-ssh
└→ OpenSSH(SSH暗号化+通信) ← GnuTLS不使用
└→ TCP接続 → GitHub
SSHが安定する理由
- OpenSSHの成熟度 — OpenSSHは25年以上の歴史を持ち、大容量データ転送でのバグは枯れています。GnuTLSとは安定性の次元が違います
- ストリーム転送 — SSHはHTTPのようなリクエスト/レスポンス構造ではなく、持続的なストリーム接続でデータを流します。チャンク分割によるオーバーヘッドがありません
- 再接続不要 — 1つのSSHセッション内でpackファイルを丸ごと転送します。HTTPのようにTLSハンドシェイクを繰り返す必要がありません
- どの環境でも同じ動作 — OpenSSHはLinux/macOS/WSLすべてに標準搭載されています。GnuTLS vs OpenSSLのような環境差がありません
SSH接続への切り替え手順
1. SSH鍵を生成する
ssh-keygen -t ed25519 -C "your-email@example.com"
パスフレーズは任意です。設定すると毎回聞かれますが、セキュリティは上がります。
2. GitHubに公開鍵を登録する
cat ~/.ssh/id_ed25519.pub
出力をコピーして、GitHub → Settings → SSH and GPG keys → New SSH key に貼ってください。
3. 接続テスト
$ ssh -T git@github.com
Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
このメッセージが出れば成功です。
4. 既存リポジトリのURLを切り替える
# 現在のURL確認
git remote -v
# origin https://github.com/user/repo.git (fetch)
# SSH URLに変更
git remote set-url origin git@github.com:user/repo.git
# 確認
git remote -v
# origin git@github.com:user/repo.git (fetch)
5. 全リポジトリを一括変換
複数リポジトリを管理している場合、一つずつ変えるのは面倒です。以下のスクリプトで一括変換できます:
cd ~/repos
for dir in */; do
if [ -d "$dir/.git" ]; then
cd "$dir"
url=$(git remote get-url origin 2>/dev/null)
if echo "$url" | grep -q "https://github.com/"; then
new_url=$(echo "$url" | sed 's|https://github.com/|git@github.com:|')
git remote set-url origin "$new_url"
echo "[OK] $dir -> SSH"
fi
cd ..
fi
done
なぜ最初からSSHにすべきなのか
HTTPS vs SSH 比較
| HTTPS | SSH | |
|---|---|---|
| 通信ライブラリ | GnuTLS(Ubuntu標準) | OpenSSH |
| 大容量ファイル | ❌ GnuTLSが落ちる | ✅ 安定 |
| 認証方式 | トークン or パスワード | 鍵認証 |
| セキュリティ | トークン漏洩リスク | 秘密鍵がPC内に留まる |
| 初回設定 | 簡単 | 鍵生成+GitHub登録が必要 |
| 長期運用 | トークン期限切れの管理 | 一度設定すれば半永久 |
初回設定が5分長いだけで、その後のすべてが楽になります。
AI時代に特に重要な理由
AIエージェント(Claude Code、Devin等)にGitHub操作をさせる場合、SSH接続だと:
- トークン管理が不要 — エージェントの設定ファイルにトークンを書かなくていい
-
トークン漏洩リスクゼロ —
.envにGitHubトークンを書く必要がない - 安定性 — エージェントが大量ファイルをpull/pushしても落ちない
特に3つ目が重要です。AIエージェントはコンテキストとして大量のファイルを扱います。ナレッジベース、設定ファイル、ログ — これらが増えるほどHTTPS接続は不安定になります。
FAQ
macOSでも同じ問題は起きますか?
macOS(Homebrewでインストールした場合)のGitはOpenSSLベースなので、GnuTLSの問題自体は起きません。ただし、SSHに切り替えるメリットはmacOSでも同じです:
- トークン管理が不要になる
- 秘密鍵がPC内に留まるためセキュリティが向上する
- 環境が変わっても同じ方法で接続できる
OS関係なく、最初からSSHにしておいて損はありません。
Git LFSを使えば解決しませんか?
Git LFS(Large File Storage)は大容量ファイルをGit本体から分離して管理する仕組みです。確かに有効ですが、通信層の問題は解決しません。
- LFSのダウンロードも結局HTTPS通信を使います
- LFSの設定・管理コストが追加で発生します
- チームメンバー全員にLFSクライアントのインストールが必要です
Git LFSは「100MB超のファイルをGitHubの制限内に収める」ための仕組みであり、「通信を安定させる」ための仕組みではありません。用途が違います。
もちろん、数百MBを超えるファイルを扱うならSSH + Git LFSの併用がベストです。ただし、今回のような35MB程度のリポジトリならSSHに切り替えるだけで十分です。
「でもOpenSSL版Gitにすれば…」
確かにGnuTLSをOpenSSLに入れ替える方法もあります。
sudo add-apt-repository ppa:git-core/ppa -y
sudo apt-get update
sudo apt-get install git -y
しかし、これはHTTPS接続の延命措置でしかありません。 別のマシンに移るたびに同じ設定が必要ですし、環境によってはPPAが使えないこともあります。
SSH接続ならどのLinux環境でもOpenSSHが入っています。追加インストール不要です。
まとめ
- GitHubにPDF・画像を入れるなら、HTTPS接続は時限爆弾です
- GnuTLSの問題はバッファ拡大やタイムアウト設定では解決しません
- SSH接続に切り替えれば根本解決。設定は5分です
- AI時代はファイルが増える一方。最初からSSHで始めてください
# これだけやってください
ssh-keygen -t ed25519 -C "your-email@example.com"
# 公開鍵をGitHubに登録
git remote set-url origin git@github.com:user/repo.git
何も考えずにSSH。以上です。
この記事が参考になったら、いいね👍をお願いします。Git × AI運用のTipsを今後も発信していきます。
📘 CLAUDE.mdのセキュリティ設計やGitHub連携のベストプラクティスを含むClaude Codeの実践ノウハウは、Zenn Book『実践Claude Code』で体系的にまとめています。