git 中的 Cherry picking 提交:大文件数据是否重复?

Cherry picking commit in git: is large file data duplicated?

我知道如果您在 git 中挑选一个提交,它会创建一个新的提交副本(使用新的 SHA 等)。

但是在内部,如果有一个大的二进制文件,数据是否重复,导致repo膨胀?或者它是否足够聪明,可以理解这是同一个 blob?

Git 足够聪明,可以继续使用相同的对象并在您的 cherry-pick 新创建的提交中引用它。 (尽管我有点理解您对重复副本的担忧,因为提交本身不仅是重复的,而且是重新创建的。)

当文件实际更改时,然后您将创建一个新对象,从而增加回购。

从用户的角度来看,将提交视为 "containing" 个文件很自然,但在内部,将提交视为 "refers to" 个文件更准确。

在其基础上,git 是一个内容索引对象存储:有一堆对象,所有对象都由它们的 SHA1 哈希值唯一标识。在此存储之上,对象被赋予表示版本控制系统组件的含义。

a good introduction to this on the Git website.

所以当您提交文件时,会存储几个对象:

  • 包含文件内容的 "blob" 对象,没有元数据
  • 一个 "tree" 包含目录列表的对象,每个文件都有一个名称和元数据,以及其当前内容的 SHA1 哈希值
  • 一个 "commit" 表示提交的对象,包括提交消息、提交时间、父提交的 SHA1 哈希值以及要使用的目录列表的 SHA1 哈希值

您通常看到的 SHA1 是此提交对象的 SHA1 - 知道这足以让 git 找到完整的提交信息,并从那里找到目录列表,然后从那里找到文件内容。

当您挑选一个提交时,git 将需要创建:

  • 一个新的提交对象,具有新的时间、父提交等
  • 可能是一个新的树对象,因为合并精心挑选的更改可能会导致某些文件不同
  • 新的 blob 对象对于任何具有新内容的文件;如果大文件的内容与之前的任何状态相同,根据定义它将具有相同的 SHA1 哈希值,因此不会再次存储

从某种意义上说,git 不是 在这里 "smart" - 它不关心 为什么 一个对象可能是重复的,它只为每个 SHA1 散列存储一个对象,如果它发现一个对象已经存在于该散列中,则假定它们是同一事物。多个可能不相关的提交引用相同文件内容的能力只是这个存储系统的一个方便的副作用。