快速解决 Git 推送时出现的 shallow update not allowed
Git 是一个强大的版本控制工具,但有时在处理大型仓库时回答来意想不到的问题。管理大型仓库的一个常见变通方法是使用「浅克隆(Shallow Clone)」,它仅下载有限的历史记录(例如最新提交),以节省时间和带宽。然而,当你尝试将此浅克隆推送到新仓库时,会遇到一个错误:remote: error: shallow update not allowed。
什么是浅克隆?
浅层克隆是使用 --depth 标志创建的 Git 仓库,该标志会限制下载的历史提交数量。例如:
git clone --depth 1 https://git.6l.ink/lz/lz此命令仅克隆最新的提交,忽略仓库的其余历史记录。浅克隆存在关键缺陷:
- 历史不完整:缺少完整的提交链,导致调试或作者追踪等操作不可靠
- 推送限制:默认情况下,你无法将浅克隆推送到新的远程代码库(因此会出现「浅层更新不允许」的错误)
Git 依赖 提交链 来确保数据完整性。每个提交都指向其父提交,形成历史时间线。当您向远程仓库推送时,Git 会检查您正在推送的提交是否在远程仓库中拥有完整的父历史。浅克隆会截断此父链。例如,如果您使用 --depth 1 进行克隆,最新提交的父指针将指向一个在本地仓库中不存在的提交。当您尝试将此提交推送到新的远程仓库(没有历史记录)时,Git 会拒绝推送:因为没有父历史,它无法验证提交的有效性。
解决方案 A: 拉取全量历史记录
要获取缺失的历史记录,使用下方命令可下载浅克隆遗漏的所有提交:
git fetch --unshallow如果仓库极大,--unshallow 可能因带宽限制而耗时较长或失败。此时可逐步增加深度直至解除浅克隆状态现在您的克隆已包含完整历史记录,请将分支(例如 main 或 master)推送到新的远程仓库。使用 -u 设置上游分支:
git push -u cnb main不过,如果新仓库在初始化时已包含 README 或许可证文件,我们会收到 failed to push some refs 错误。可通过合并远程仓库的初始提交到本地分支来解决:
git pull --allow-unrelated-histories cnb main
git push -u cnb main--allow-unrelated-histories 标志让 Git 合并两个不相关的提交历史记录(您的本地仓库和远程仓库的初始提交)
解决方案 B: 使用补丁
缺点:重写提交哈希,丢失原始历史元数据
在浅克隆中,创建所有变更的补丁:
git format-patch --root HEAD创建空远程仓库的一个全新克隆:
git clone <new-repo-url> new-repo
cd new-repo应用补丁:
git am /path/to/shallow-clone/*.patch推送应用的提交:
git push -u origin main解决方案 C: Rebase
如果你希望保持代码库原样,包括在浅层初始提交之后添加的新提交,另一个选项是:通过交互式变基来修改此提交。
启动一个包含第一个根提交的交互式变基:
git rebase --interactive --root将初始提交的 pick 更改为 edit,通常只需要修改第一行,然后保存并关闭文件。
如果你克隆仓库时的深度大于 1,你可能需要对所有这些提交执行相同操作。或者,在交互式变基期间为所有这些提交执行 fixup。
将此提交转换为常规的、非浅层提交:
git commit --amend --no-edit这也会更改提交 ID,并将你添加为此初始提交的合著者。
完成变基操作:
git rebase --continue