Git checkout耗时超2小时求助:自建GitLab分支切换异常排查
我正在测试自建的GitLab实例,已经把本地Git仓库推送到了这个实例上。GitLab上的仓库占用14GB空间,包含多个LFS对象。
用命令$ git clone http://[ip:port]/repo/bavoo.git克隆主分支只需要1-2分钟,克隆日志如下:
$ git clone http://[ip:port]/repo/bavoo.git Cloning into 'bavoo'... remote: Enumerating objects: 773299, done. remote: Total 773299 (delta 0), reused 0 (delta 0), pack-reused 773299 Receiving objects: 100% (773299/773299), 541.07 MiB | 2.44 MiB/s, done. Resolving deltas: 100% (633879/633879), done.
但执行$ git checkout bavoo_test切换分支时耗时超过2小时(我中途终止了操作),完全不清楚Git在后台做什么。请问该怎么排查这个分支切换耗时过长的问题?
补充环境信息
- macOS版本:10.15.3 (19D76)
- Git版本:
git version 2.24.1 - Git LFS版本:
git-lfs/2.8.0 (GitHub; darwin amd64; go 1.12.7)
编辑补充:git lfs env输出
Endpoint=http://[ip:port]/repo/bavoo.git/info/lfs (auth=basic) LocalWorkingDir=/Users/daniel/Desktop/bavoo LocalGitDir=/Users/daniel/Desktop/bavoo/.git LocalGitStorageDir=/Users/daniel/Desktop/bavoo/.git LocalMediaDir=/Users/daniel/Desktop/bavoo/.git/lfs/objects LocalReferenceDirs= TempDir=/Users/daniel/Desktop/bavoo/.git/lfs/tmp ConcurrentTransfers=3 TusTransfers=false BasicTransfersOnly=false SkipDownloadErrors=false FetchRecentAlways=false FetchRecentRefsDays=7 FetchRecentCommitsDays=0 FetchRecentRefsIncludeRemotes=true PruneOffsetDays=3 PruneVerifyRemoteAlways=false PruneRemoteName=origin LfsStorageDir=/Users/daniel/Desktop/bavoo/.git/lfs AccessDownload=basic AccessUpload=basic DownloadTransfers=basic UploadTransfers=basic GIT_EXEC_PATH=/usr/local/Cellar/git/2.24.1/libexec/git-core
排查思路和解决方案
先别着急,咱们一步步拆解问题——克隆快但切换分支慢,大概率和LFS对象的拉取、Git的文件系统操作或者分支间的差异有关。下面是具体的排查步骤:
1. 先看Git切换时到底在做什么:开启调试日志
Git和Git LFS都有详细的调试日志,能帮你精准定位卡在哪一步。重新执行checkout时加上调试参数:
# 开启Git全局调试,看所有操作细节 GIT_TRACE=1 GIT_CURL_VERBOSE=1 git checkout bavoo_test # 或者单独追踪LFS的操作日志 GIT_LFS_TRACE=1 git checkout bavoo_test
执行后会输出每一步的操作细节,比如是在拉取LFS对象、校验文件还是处理Git对象,你可以根据日志判断是卡在LFS下载阶段,还是Git本身的文件更新环节。
2. 检查分支间的LFS对象差异
切换分支时,Git LFS需要把工作区里的LFS指针替换成实际文件,如果bavoo_test分支和当前分支有大量不同的LFS对象,就会触发大量下载和文件替换操作。你可以先对比两个分支的LFS对象差异:
# 查看两个分支间差异的文件(筛选你仓库里的LFS后缀) git diff --name-only --diff-filter=d HEAD bavoo_test | grep -E '\.(png|jpg|zip|你的LFS文件后缀)$' # 统计差异的LFS对象数量 git diff HEAD bavoo_test | grep 'oid sha256:' | wc -l
如果差异数量特别多,那就是LFS下载的问题——可以检查你的GitLab LFS服务的带宽,或者本地和GitLab实例的网络连接速度。另外,你的Git LFS版本是2.8.0,比较老旧,建议升级到最新稳定版(比如v3.x+),新版本优化了并发下载和文件处理逻辑,能显著提升速度。
3. 检查本地磁盘性能
macOS 10.15的磁盘IO如果有问题(比如用的是机械硬盘、磁盘空间不足、APFS容器异常),也会导致大量文件替换时变慢。你可以:
- 检查磁盘剩余空间:
df -h /Users/daniel/Desktop/bavoo,确保有足够空间(至少是仓库大小的1.5倍) - 用
diskutil verifyVolume /检查磁盘是否有错误(需要关闭SIP或在恢复模式下执行) - 临时把仓库移到SSD上测试,如果速度变快,说明就是磁盘性能拖了后腿
4. 优化Git配置提升效率
老版本的Git在处理大仓库时可能没开启一些关键优化,你可以试试开启这些配置:
# 开启文件系统缓存,减少文件状态检查时间 git config core.fscache true # 调整LFS并发下载数(默认是3,你可以调到5-10试试) git config lfs.concurrenttransfers 8 # 如果只需要分支里的部分文件,开启稀疏 checkout 减少文件处理量 git config core.sparseCheckout true
另外,你可以先执行git fetch origin bavoo_test拉取目标分支的所有对象,再执行checkout——有时候checkout时同时拉取对象会导致阻塞,分开操作可能更快。
5. 检查GitLab实例的LFS服务状态
虽然克隆正常,但切换分支时LFS的请求路径可能不同。你可以在GitLab后台查看LFS日志(一般路径是/var/log/gitlab/gitlab-rails/lfs.log),看是否有请求超时、权限错误或者带宽限制的情况。同时确认GitLab的LFS存储是否在高性能磁盘上,有没有IO瓶颈。
6. 临时跳过LFS验证做测试
如果怀疑是LFS导致的问题,可以临时关闭LFS自动下载,看看切换分支的速度:
git config lfs.skipdownload true git checkout bavoo_test
如果这时候速度正常,那就坐实了是LFS的下载或文件处理问题,再回到步骤2和3针对性解决。
最后别忘了升级你的Git和Git LFS版本——2.24.1的Git是2019年的版本,很多大仓库的优化都是后续版本加上的,升级后大概率能解决一些隐性问题。
内容的提问来源于stack exchange,提问作者Daniel Stephens




