使用--depth 1进行浅克隆,创建提交并再次拉取更新是否安全?

310
git clone 命令中,--depth 1 选项表示创建一个 浅复制(shallow clone) ,历史记录被截断到指定的修订版本数。浅存储库有许多限制(您不能从它克隆或获取,也不能将其推送到其他地方),但如果您只对具有长时间历史记录的大型项目的最近历史记录感兴趣,并想以补丁的形式发送修复,则足够使用。
但我成功地进行了浅克隆、提交了一些更改,并将这些更改推送回了原始 (bare clone) 的源。 这对我来说是有道理的——我的提交处于可识别的源上的 HEAD 之上,因此似乎没有任何理由不这样做。但手册却说了另外一种情况。
我喜欢浅克隆的想法——比如 Drupal 核心:当我从 7 开始时,我不需要知道在 Drupal 4 中发生了什么。但我不想自己给自己设置障碍。
那么,进行浅克隆,开发提交,在保持与源更新同步时再次拉取是否安全呢?

13
这里有一个关于克隆深度的不错讨论:https://dev59.com/-Gw05IYBdhLWcg3w_WxN - Andy
是的,我也看过了,谢谢安迪。 --orphan 的概念似乎相似,我打算试一下。但文档与现实不符仍让我有点不安 [因为谁能说 --orphan 的文档是正确的呢?!] - artfulrobot
发现了另一个关于使用截断历史记录的讨论,链接为:https://dev59.com/tG025IYBdhLWcg3w6aUX#5724782。但是它对我没有帮助。 - artfulrobot
1
Git 1.9(2014年第一季度)将完全支持浅层仓库克隆!请参见下面的我的回答 - VonC
1
Git 2.5(2015年第二季度)支持单个获取提交!我已经编辑了我的答案,引用“从远程git存储库拉取特定提交”。 - VonC
2个回答

330
请注意,Git 1.9/2.0 (2014年第一季度)已经移除了这个限制。
参见提交记录82fba2b,作者为Nguyễn Thái Ngọc Duy (pclouds)

现在,由于git支持来自或到达浅克隆的数据传输,这些限制不再存在。

文档现在的内容如下

--depth <depth>::

创建一个“浅层”克隆,其历史记录被截断到指定的修订版本数。 这源于像0d7d285, f2c681cc29a7b8这样的提交,它们支持使用浅层克隆进行克隆、发送/接收包。smart-http现在也支持浅层获取/克隆

所有细节都在 "shallow.c: 选择新提交以更新 .git/shallow 的8个步骤" 中。

更新于2015年6月:Git 2.5甚至允许获取单个提交
(极限浅层情况)



2016年1月更新:Git 2.8(2016年3月)现在正式记录了获取最小历史记录的做法。
请参见commit 99487cf, commit 9cfde9e (2015年12月30日), commit 9cfde9e (2015年12月30日), commit bac5874 (2015年12月29日)和commit 1de2e44 (2015年12月28日),作者为Stephen P. Smith (``)
(由Junio C Hamano -- gitster --commit 7e3e80a中合并,2016年1月20日)

这是 "Documentation/user-manual.txt"

<<def_shallow_clone,浅克隆>> 是通过指定 git-clone --depth 开关来创建的。
可以使用 git-fetch --depth 开关更改深度,或使用 --unshallow 恢复完整历史记录。

<<def_shallow_clone,浅克隆>> 中进行合并只有在最近的历史记录中存在合并基础时才能正常工作。
否则,它将像合并不相关的历史记录一样,并可能导致巨大的冲突。
这个限制可能使这样的存储库不适合用于基于合并的工作流程。

更新 2020:

  • git 2.11.1 引入了选项 git fetch --shallow-exclude=,以防止获取所有历史记录。
  • git 2.11.1 引入了选项 git fetch --shallow-since=,以防止获取旧的提交。

想了解浅克隆的更新过程,请参阅 "如何更新git浅克隆?"。


Richard Michael所述:

要回溯历史记录:git pull --unshallow

Olle Härstedt评论中补充道:

要回溯部分历史记录:git fetch --depth=100


9
只需要这么多文字来表示“是的”,只要您的 Git 版本不是四年前的版本,且合并基础在最近的历史记录中。 - user3064538
9
@Boris这个答案对我有很大帮助,因为我曾经怀疑使用浅克隆(shallow clone)。以前,当我进行提交和合并时,它有时会出现问题。这个答案简要介绍了为什么现在它可行的历史以及如何正确地执行它。 - Yana Agun Siswanto
我的需求是,在浅克隆之后,我需要将此代码提交到一个新的远程存储库。由于这个代码的巨大大小,我无法取消浅克隆。如何将这个浅克隆推送到一个新的存储库而不会出现任何问题(目前遇到了浅对象更新失败的问题)?有什么想法吗? - Tiny
@Tiny,我建议你使用一个单独的本地仓库,它可以引用你的浅克隆文件夹。你能提出一个单独的问题吗? - VonC

6
看一下我类似问题的一些答案:why-cant-i-push-from-a-shallow-clone以及git列表中最近的主题链接。

归根结底,“深度”测量在不同的repo之间不一致,因为它们是根据各自的HEAD进行测量,而不是(a)你的Head,或者(b)你克隆/获取的提交,或者(c)你还有其他想法。

困难的部分是正确获取自己的用例(即自洽),这样分布式存储库,因此可能发散的存储库仍将愉快地一起工作。

看起来checkout --orphan是正确的“设置”阶段,但仍缺乏对“克隆”步骤的清晰(即简单易懂的一行命令)指导。相反,看起来你必须初始化一个repo,设置一个remote跟踪分支(你只需要一个分支吗?),然后fetch这个单独的分支,这感觉很冗长,更容易出错。

编辑:关于“克隆”步骤,请参见此答案


1
谢谢Philip。获取远程分支仍将拉取整个历史记录(据我所知)。你关于相对深度的想法是正确的,但实际上我想要一些适当的历史点(例如在我的情况下,像git merge-base 7.x 7.0)。 - artfulrobot
@artfulrobot:'--orphan' 方法允许您创建一个短小的、窄的“克隆”(即一个聚焦的片段),然后将其用作真正的存储库。这是我还没有尝试过的东西,但我很快就需要证明它的价值。 - Philip Oakley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接