Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git是否以某种方式有效地存储子提交列表_Git - Fatal编程技术网

Git是否以某种方式有效地存储子提交列表

Git是否以某种方式有效地存储子提交列表,git,Git,Git提交对象只存储作者、日期、消息、父提交哈希和根目录哈希 所以,如果我想知道这个提交中存在哪些子项(当然只考虑一个存储库),Git是如何做到的?基本上。但Git如何在内部做到这一点?实施的效率如何?它的时间复杂性是什么?它是否从每一个分支头开始,穿过所有可能的路径,然后收集所有可能的孩子?或者它做了一些聪明的缓存或其他方法 我可以想象,如果你想知道一个非常老的提交的孩子,遍历会变得非常慢。它基本上与整个存储库的大小成线性关系。不知道如何将提交存储在Git中的用户甚至可能会假定此类请求的时间是

Git提交对象只存储作者、日期、消息、父提交哈希和根目录哈希

所以,如果我想知道这个提交中存在哪些子项(当然只考虑一个存储库),Git是如何做到的?基本上。但Git如何在内部做到这一点?实施的效率如何?它的时间复杂性是什么?它是否从每一个分支头开始,穿过所有可能的路径,然后收集所有可能的孩子?或者它做了一些聪明的缓存或其他方法

我可以想象,如果你想知道一个非常老的提交的孩子,遍历会变得非常慢。它基本上与整个存储库的大小成线性关系。不知道如何将提交存储在Git中的用户甚至可能会假定此类请求的时间是恒定的,所以这是一个很大的区别



我真的很想知道这一点,而不是别的什么。我为什么想知道这些并不重要。我只是想知道。这就是为什么我不总是解释我是如何提出这个问题的。git遍历路径是从子对象到父对象的原因是提交对象不能依赖于它的子对象

如果对提交对象中的每个子对象都存储了引用,那么每次添加、删除或重命名子对象时,提交及其子对象的SHA都会发生更改(这里经常发生这种情况)。这将破坏整个简单的对象存储,因为提交不会有稳定的SHA


因此,在这个约束下,只有父级可以存储,并且由于这个约束,没有替代缓存。您所要求的查询(我假定类似于SHA之后的next 5 commits)根本不现实,但可以通过指定最后一个子项的SHA和到父项的遍历路径以另一种方式进行表述。

在典型的git存储库中,对于任何足够旧的提交:

  • 它的孩子们分布在世界各地,从未在一个存储库和
  • 其中一些已经不存在了(即使在单个存储库中,它们也会及时消失)
根本没有办法找到它们,也没有理由这样做。大多数都不有趣


感兴趣的子级是合并到某个感兴趣的分支中的子级,可以从那里开始查找。

Git有一个命令,可以显示存储库及其远程存储库的所有分支,这些分支是提交的子级:

git branch --all --contains <commithash>
git分支--all--contains
不过,这只会让孩子们成为树枝的头。我必须承认,我并不真正理解你问题的严重性


Edit:从我在Git的代码(Git的源代码树中的文件
commit.c
)中看到的内容来看,对于每个引用,调用函数
的子代,该函数递归浏览图形,以确定引用是否在其祖先中包含提交。

如果是通过“child”你是说提交之后的提交,git不会将其存储在任何地方。一旦进行了提交,它将存储在其内容的散列下,因此您不能修改它,而且在创建提交时,显然不存在提交的子项。是的,效率不高。幸运的是,我们几乎不需要了解儿童-这根本不在Git工作流中。-1感谢您没有解释为什么您需要这样做。Git开发人员不会做任何他们没有合理用例的事情。在没有实际用例的情况下要求某些东西几乎被认为是一种罪恶。@GaryFixler:当然,提交是不能修改的。但Git可以将这些信息保存在其他地方,比如缓存中。显然,事实并非如此。这就是我想知道的,当然足够了。这不是问题所在。问题是它是否也存储孩子。如果没有,并且在一个单独的缓存中也没有其他内容,正如您的答案所示,那么计算它们是没有效率的。这就是我想知道的。@Albert没有单独的孩子缓存,我对此做了解释。当然,Git显然不能将孩子存储在提交中。但是Git可以有一个单独的缓存/存储。就像它存储其他可变对象一样(例如分支头引用)。@Albert抱歉,我不确定什么是明显的。是的,你是对的,缓存是可以构建的,尽管我不确定它是否可以与分支和标记的存储相媲美,尤其是在它有用的用例中。是的,可能这种缓存的不同结构会更有意义。不管怎么说,这就是我想知道的——Git是否有这样的缓存或者做了其他聪明的事情,或者它是否采用了天真的规范方式,即通过父引用进行遍历。当然,如果考虑到不同的分叉回购协议。但显然,考虑一个单一的回购问题对于孩子来说是有意义的。问题不是我会怎么做(Git命令),而是Git是如何做的(内部的)以及它是如何高效地完成的(时间复杂度)。