Git のトラブルシューティング

Git を使っていると、時として思い通りに動かないことがあります。ここでは、Gitのトラブルシューティングと問題解決のヒントをいくつか紹介します。

パイプ切れエラーgit push

Broken pipe’ エラーは、リモートリポジトリにプッシュしようとすると発生します。通常、プッシュ時に

Write failed: Broken pipe
fatal: The remote end hung up unexpectedly

このイシューを解決するには、以下の方法が考えられます。

GitのPOSTバッファサイズを大きくする

SSH ではなく HTTP で Git を使っている場合は、Git の設定で POST バッファサイズを大きくしてみましょう。

クローン中のエラーの例fatal: pack has bad object at offset XXXXXXXXX: inflate returned -5

ターミナルを開いて入力してください:

git config http.postBuffer 52428800

値はバイト単位で指定されるため、上記の場合、バッファサイズは50MBに設定されています。デフォルトは1MBです。

RPC に失敗しました。curl 92 HTTP/2 ストリーム 0 がきれいに閉じられませんでした:INTERNAL_ERROR (err 2)

この問題は、インターネット接続が遅いことが原因かもしれません。SSH ではなく Git over HTTP を使っている場合は、以下の修正方法を試してみてください:

  • Git の設定でgit config http.postBuffer 52428800 を使って POST バッファ・サイズを大きくしてください。
  • git config http.version HTTP/1.1 を使ってHTTP/1.1 プロトコルに切り替えましょう。

どちらの方法でもエラーが解決しない場合は、別のインターネット・サービス・プロバイダーが必要かもしれません。

SSH設定の確認

SSH 経由でプッシュする場合、まず SSH の設定を確認してください。’Broken pipe’ エラーは SSH の根本的な問題 (認証など) が原因となっていることがあります。SSHのトラブルシューティングドキュメントにある指示に従って、SSHが正しく設定されていることを確認してください。

GitLab 管理者でサーバーにアクセスしている場合は、クライアントやサーバーで SSHkeep-alive を設定することでセッションのタイムアウトを防ぐこともできます。

note
クライアントとサーバーの両方を設定する必要はありません。

クライアント側でSSHを設定するには

  • UNIXでは、~/.ssh/config (ファイルが存在しない場合は作成)を編集し、追加または編集します:

     Host your-gitlab-instance-url.com
       ServerAliveInterval 60
       ServerAliveCountMax 5
    
  • Windowsでは、PuTTYを使用している場合、セッションのプロパティに移動し、「接続」に移動し、「セッションをアクティブに保つためのヌルパケットの送信」の下で、Seconds between keepalives (0 to turn off)60 に設定します。

サーバー側でSSHを設定するには/etc/ssh/sshd_config を編集し、追加します:

ClientAliveInterval 60
ClientAliveCountMax 5

を追加してください。git repack

pack-objects’ タイプのエラーも表示される場合は、リモートリポジトリにプッシュする前にgit repack を実行してみてください:

git repack
git push

Git クライアントのアップグレード

古いバージョンの Git (< 2.9), consider upgrading to >= 2.9 (Broken pipe when push to Git repository を参照)) を使っている場合は、Git クライアントをアップグレードしましょう。

ssh_exchange_identification エラー

Git を SSH 経由でプッシュまたはプルしようとすると、次のようなエラーが発生することがあります:

Please make sure you have the correct access rights
and the repository exists.
...
ssh_exchange_identification: read: Connection reset by peer
fatal: Could not read from remote repository.

あるいは

ssh_exchange_identification: Connection closed by remote host
fatal: The remote end hung up unexpectedly

あるいは

kex_exchange_identification: Connection closed by remote host
Connection closed by x.x.x.x port 22

このエラーは通常、SSH デーモンのMaxStartups の値が SSH 接続を制限していることを示しています。この設定は、SSH デーモンへの認証されていない同時接続の最大数を指定します。すべての接続が最初は「未認証」であるため、これは適切な認証情報 (SSH キー) を持つユーザーに影響します。デフォルト値は10 です。

GitLab サーバーで/etc/ssh/sshd_config の値を追加または変更して、MaxStartups を増やします:

MaxStartups 100:30:200

100:30:200 の値を追加または変更することで、GitLabサーバーの を増やすことができます。

MaxStartups の値を変更したら、設定にエラーがないか確認してください。

sudo sshd -t -f /etc/ssh/sshd_config

設定チェックがエラーなしで実行された場合は、SSH デーモンを再起動して変更を有効にしても問題ありません。

# Debian/Ubuntu
sudo systemctl restart ssh

# CentOS/RHEL
sudo service sshd restart

git push /中のタイムアウトgit pull

リポジトリからのプル/プッシュが50秒以上かかると、タイムアウトがイシューされます。以下の例のように、実行されたオペレーション数とそれぞれの時間のログがコンテナに記録されます:

remote: Running checks for branch: master
remote: Scanning for LFS objects... (153ms)
remote: Calculating new repository size... (cancelled after 729ms)

これは、どのオペレーションがうまく動作していないのかをさらに調査し、GitLab にサービスを改善するための情報を提供するために使うことができます。

git clone over HTTP はtransfer closed with outstanding read data remaining エラーで失敗します。

古いリポジトリや大きなリポジトリのクローンを作成すると、以下のエラーが発生することがあります:

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

この問題は、Git自体が大きなファイルや大量のファイルを扱えないためによく起こります。Git LFSはこの問題を回避するために作られました。しかし、これにも限界があります。通常、次のような原因があります:

  • リポジトリ内のファイル数。
  • 履歴の修正回数。
  • リポジトリ内の大きなファイルの存在。

根本的な原因はさまざまなので、複数の潜在的な解決策が存在し、複数の解決策を適用する必要があるかもしれません:

  • 大きなリポジトリのクローンを作成するときにこのエラーが発生する場合は、クローンの深さを 1 の値まで下げることができます:

     variables:
       GIT_DEPTH: 1
    
  • ローカルの Git 設定にあるhttp.postBufferの値を、デフォルトの 1 MB からリポジトリサイズよりも大きな値に増やすことができます。例えば、git clone が 500 MB のリポジトリのクローン作成に失敗する場合は、http.postBuffer524288000に設定します:

     # Set the http.postBuffer size, in bytes
     git config http.postBuffer 524288000
    
  • サーバー側でhttp.postBuffer を増やすことができます:

    1. GitLab インスタンスのgitlab.rb ファイルを修正します:

      gitaly['configuration'] = {
        # ...
        git: {
          # ...
          config: [
            # Set the http.postBuffer size, in bytes
            {key: "http.postBuffer", value: "524288000"},
          ],
        },
      }
      
    2. この変更を適用した後、設定変更を適用します:

      sudo gitlab-ctl reconfigure
      

例えば、リポジトリの履歴が非常に長く、大きなファイルがない場合、深さを変更することで問題が解決するはずです。しかし、リポジトリに非常に大きなファイルがある場合、深度 1 でも大きすぎることがあり、postBuffer 変更が postBuffer必要になります。postBuffer ローカルを増やしても postBufferバックエンドの NGINX 値が小さすぎる場合、エラーは持続します。

サーバーを変更することが常に選択肢であるとは限らず、潜在的なリスクが高くなります。まずローカルの変更を試みてください。

SSH 経由の Git フェッチで LDAP ユーザーのパスワードが期限切れのエラー

GitLabの自己管理インスタンスでgit fetch がこのHTTP 403 Forbidden エラーを返した場合、GitLabデータベース内のこのユーザーのパスワード有効期限 (users.password_expires_at) は過去の日付になっています:

Your password expired. Please access GitLab from a web browser to update your password.

SSOアカウントで行われたリクエストで、password_expires_atnull でない場合、このエラーを返します:

"403 Forbidden - Your password expired. Please access GitLab from a web browser to update your password."

このイシューを解決するには、パスワードの有効期限を更新します:

  • gitlab-rails console を使用します:

     gitlab-rails console
     user.update!(password_expires_at: nil)
    
  • gitlab-psql を使用します:

     # gitlab-psql
     UPDATE users SET password_expires_at = null WHERE username='<USERNAME>';
    

このバグはこのイシューでレポーターされました。

Git フェッチ時のエラー:”HTTP Basic: アクセス拒否”

Git over HTTP(S)を使っているときにHTTP Basic: Access denied エラーが発生した場合は、二要素認証のトラブルシューティングガイドを参照してください。

401 成功時に記録されるエラーgit clone

HTTP 経由でリポジトリのクローンを作成する場合、production_json.log ファイルに401 (unauthorized) という初期ステータスが表示され、すぐに200.

{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":401,
   "time":"2023-04-18T22:55:15.371Z",
   "remote_ip":"x.x.x.x",
   "ua":"git/2.39.2",
   "correlation_id":"01GYB98MBM28T981DJDGAD98WZ",
   "duration_s":0.03585
}
{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":200,
   "time":"2023-04-18T22:55:15.714Z",
   "remote_ip":"x.x.x.x",
   "user_id":1,
   "username":"root",
   "ua":"git/2.39.2",
   "correlation_id":"01GYB98MJ0CA3G9K8WDH7HWMQX",
   "duration_s":0.17111
}

HTTP ベーシック認証の仕組みから、HTTP 経由の Git オペレーションではこのような401 ログが最初に表示されることを想定しておく必要があります。

Gitクライアントがクローンを開始するとき、GitLabに送られる最初のリクエストは認証の詳細を提供しません。GitLabはそのリクエストに対して401 Unauthorized 。数ミリ秒後、Gitクライアントは認証の詳細を含むフォローアップリクエストを送信します。この二回目のリクエストは成功し、200 OK のログが返されます。

401 のログエントリーに対応する200 のログエントリーがない場合、Git クライアントはどちらかを使っている可能性があります:

  • パスワードが間違っています。
  • 有効期限切れまたは失効したトークン。

修正しないと、403 (Forbidden) エラー が発生する可能性があります。

403 Git のオペレーションを HTTP で行う際のエラー

HTTP 経由で Git のオペレーションを行う際に403 (Forbidden) エラーが発生するのは、あなたの IP アドレスが認証の失敗によってブロックされていることを示しています:

fatal: unable to access 'https://gitlab.com/group/project.git/': The requested URL returned error: 403

403production_json.log で見ることができます:

{
   "method":"GET",
   "path":"/group/project.git/info/refs",
   "format":"*/*",
   "controller":"Repositories::GitHttpController",
   "action":"info_refs",
   "status":403,
   "time":"2023-04-19T22:14:25.894Z",
   "remote_ip":"x.x.x.x",
   "user_id":1,
   "username":"root",
   "ua":"git/2.39.2",
   "correlation_id":"01GYDSAKAN2SPZPAMJNRWW5H8S",
   "duration_s":0.00875
}

IPアドレスがブロックされている場合、対応するログエントリがauth_json.log に存在します:

{
    "severity":"ERROR",
    "time":"2023-04-19T22:14:25.893Z",
    "correlation_id":"01GYDSAKAN2SPZPAMJNRWW5H8S",
    "message":"Rack_Attack",
    "env":"blocklist",
    "remote_ip":"x.x.x.x",
    "request_method":"GET",
    "path":"/group/project.git/info/refs?service=git-upload-pack"}

認証に失敗した場合の禁止制限は、セルフマネージドインスタンスか GitLab.com を使っているかによって異なります。