Git 故障排查

有时事情并没有像原本应该的那样工作,或者如你所期望的那样你正在使用 Git。以下是有关 Git 使用的故障排除和解决问题的一些提示。

git push Broken pipe 错误

尝试推送到远程存储库时可能会发生 “Broken pip” 错误。推送时,您通常会看到:

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

为了解决这个问题,这里有一些可能的解决方案。

增加 Git 中的 POST 缓冲区大小

如果您使用 Git over HTTP 而不是 SSH,您可以尝试增加 Git 中的 POST 缓冲区大小配置。

克隆期间的错误示例: fatal: pack has bad object at offset XXXXXXXXX: inflate returned -5

打开终端并输入:

git config http.postBuffer 52428800

该值以字节为单位,因此在上述情况下,缓冲区大小已设置为 50MB。默认值为 1MB。

检查您的 SSH 配置

如果通过 SSH 推送,首先检查您的 SSH 配置,因为 “Broken pipe” 错误有时是由 SSH 的潜在问题引起的(例如验证)。

如果您是具有服务器访问权限的管理员,您还可以通过在客户端或服务器上配置 SSH keep-alive 来防止会话超时。

note不需要同时配置客户端和服务器。

要在客户端配置 SSH

  • 在 UNIX 上,编辑 ~/.ssh/config(如果文件不存在则创建该文件)并添加或编辑:

    Host your-gitlab-instance-url.com
      ServerAliveInterval 60
      ServerAliveCountMax 5
    
  • 在 Windows 上,如果您使用 PuTTY,请转到会话属性,然后导航到”连接”并在”发送空数据包以保持会话活动”下,将保持连接之间的秒数(0 表示关闭)设置为 60

要在服务器端配置 SSH,编辑 /etc/ssh/sshd_config 并添加:

ClientAliveInterval 60
ClientAliveCountMax 5

运行 git repack

如果 ‘pack-objects’ 类型错误也被显示,您可以尝试再次推送到远程存储库之前运行git repack

git repack
git push

升级您的 Git 客户端

如果您运行的是旧版本的 Git(< 2.9),请考虑升级到 >= 2.9(请参阅推送到 Git 仓库时 pipe 损坏)。

ssh_exchange_identification 错误

用户在尝试通过 Git over 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”。

通过添加或修改 /etc/ssh/sshd_config 中的值来增加极狐GitLab 服务器上的 MaxStartups

MaxStartups 100:30:200

100:30:200 表示最多允许 100 个 SSH 会话不受限制,之后 30% 的连接将被丢弃,直到达到 200 的绝对最大值。

配置完成后,重新启动 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)

这可用于进一步调查哪些操作性能不佳,并提供有关如何执行的更多信息以改善服务。

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
    
  • 可以增加 http.postBuffer 值从默认的 1 MB 值变为大于仓库大小的值。例如,如果在克隆 500 MB 仓库时 git clone 失败,应该将 http.postBuffer 设置为 524288000

    # Set the http.postBuffer size, in bytes
    git config http.postBuffer 524288000
    
  • 可以在服务器端增加 http.postBuffer

    1. 修改极狐GitLab 实例的 gitlab.rb 文件:

      omnibus_gitconfig['system'] = {
        # Set the http.postBuffer size, in bytes
        "http" => ["postBuffer = 524288000"]
      }
      
    2. 修改后应用配置更改:

      sudo gitlab-ctl reconfigure
      

例如,如果仓库具有很长的历史并且没有大文件,则更改深度应该可以解决问题。但是,如果仓库有非常大的文件,即使深度为 1 也可能太大,因此需要更改 postBuffer。如果增加了本地 postBuffer 但是后端的 NGINX 值仍然太小,错误仍然存在。

修改服务器并不总是一种选择,并且会引入更多潜在风险。首先尝试本地更改。