在Windows 10的Git Bash中使用rsync与cp备份Git服务器文件时为何错误生成空文件?
问题分析与解决方案
你遇到的这个问题在Windows环境下使用Git Bash的类Unix工具复制大文件时并不少见,尤其是处理超过4GB的Git pack文件这类大文件时。下面是可能的原因和对应的解决办法:
可能的原因
- 旧版本工具的兼容性缺陷:你使用的rsync 3.0.8和cp 8.32都是比较老旧的版本(rsync 3.0.8发布于2010年),它们对Windows NTFS文件系统的大文件(尤其是单文件超过4GB)支持存在bug,可能在读取或写入时悄悄截断文件,但工具本身不会返回错误码。
- Git Bash的环境模拟限制:Git Bash基于MinGW模拟Unix环境,在处理Windows挂载的磁盘文件时,可能存在文件读取缓存或系统调用的兼容性问题,导致无法完整读取源文件的全部字节。
- 稀疏文件处理不当:Git的pack文件可能被标记为稀疏文件,旧版本的rsync/cp在处理这类文件时没有正确展开数据,最终导致备份文件缺失内容。
解决办法
1. 升级rsync到最新版本
Git for Windows已经更新了内置的rsync版本,对Windows环境的兼容性大幅提升。你可以安装最新版的Git for Windows,重新打开Git Bash后,使用新版本rsync执行备份,推荐加上--whole-file参数避免增量传输的潜在问题:
cd /backup_drive && \ rsync \ --verbose \ --checksum \ --archive \ --delete \ --progress \ --whole-file \ "../server_drive/git-server/repo/objects/pack" \ "../backup_drive/server_drive/git-server/repo/objects"
2. 使用Windows原生工具替代
既然手动复制可以正常完成,说明Windows原生的文件系统处理逻辑没有问题。你可以在Git Bash中直接调用Windows自带的robocopy命令,它对NTFS文件系统的大文件、权限、稀疏文件等特性支持更完善:
robocopy \ /E \ /COPYALL \ /R:3 \ /W:5 \ /V \ /NP \ "/c/server_drive/git-server/repo/objects/pack" \ "/d/backup_drive/server_drive/git-server/repo/objects/pack"
(注意把/c/和/d/替换成你实际的盘符映射,比如源盘是D盘就用/d/)
3. 调整文件系统设置
- 确保源盘和备份盘都是NTFS格式,FAT32不支持单个超过4GB的文件,会直接导致文件截断。
- 关闭磁盘的压缩或加密功能:右键磁盘→属性→取消勾选“压缩此驱动器以节省磁盘空间”和“加密内容以便保护数据”,避免类Unix工具处理这些特性时出错。
4. 验证文件完整性
复制完成后,用以下命令对比源文件和备份文件的SHA256哈希,确保复制正确:
# 计算源文件哈希 sha256sum "../server_drive/git-server/repo/objects/pack/pack-558bb0397370ee5026dd0ce32579908064ed9e72.pack" # 计算备份文件哈希 sha256sum "../backup_drive/server_drive/git-server/repo/objects/pack/pack-558bb0397370ee5026dd0ce32579908064ed9e72.pack"
或者使用Windows原生命令(Git Bash或CMD中均可执行):
certutil -hashfile "C:\server_drive\git-server\repo\objects\pack\pack-558bb0397370ee5026dd0ce32579908064ed9e72.pack" SHA256 certutil -hashfile "D:\backup_drive\server_drive\git-server\repo\objects\pack\pack-558bb0397370ee5026dd0ce32579908064ed9e72.pack" SHA256
内容的提问来源于stack exchange,提问作者TimFinnegan




