gitmerge的策略是否保留了垃圾收集中的提交



在我们的项目中,我们有一个模型比较器,它检查代码的性能,并将统计信息与提交的git哈希一起保存。问题是,在许多情况下,这个提交稍后会成为孤立的,并且我们不能仅使用git哈希来检索提交。

我提出了一个解决方案,在保存统计信息后立即在一个特殊的shelter分支上合并提交。这将允许我们有一个单独的分支来负责保持提交的有效性(甚至可以对该分支进行限制,以防止在合并后丢失提交)。然而,这个解决方案打开了另一个问题,即在从脚本自动合并时可能会出现不希望出现的合并冲突;我的最终想法是使用ours策略进行合并:git merge -s ours <hash>。这种合并策略不从我们正在合并的提交中提取任何一行,只生成一个属于shelter的伪提交,而该伪提交是提交的依赖项,否则可能会成为孤立的。

为了让团队相信这种策略是有效的,我需要从git引用中提供一份书面证据,明确说明即使是-s ours策略也可以避免垃圾收集(这种策略不从源提交中提取一行代码,这会带来一些不确定性)。到目前为止,我发现了一个模糊的说法:

git-gc非常努力地不删除被引用的对象存储库中的任何位置。特别是,它不仅由当前分支和标记集引用的对象索引引用的对象、远程跟踪分支、保存的笔记通过refs/notes/下的git notes,reflogs(可能引用提交在后来被修改或重新缠绕的分支中),以及refs/*命名空间。如果希望删除某些对象如果不是,请检查所有这些位置并决定是否在您的情况下删除这些引用是有意义的。

这句话没有说明不同的合并策略,我预计细节会很糟糕。例如,git merge --squash,作为";合并";,没有保留依赖关系。

我的问题是,是否有一个明确的声明来解决git merge -s ours策略的歧义。

长问题,短答案:是。

稍长的答案:使用ours策略只会影响合并提交中使用的文件内容(那些来自分支的内容已将合并到中)。但是,来自内容被丢弃的另一个分支的提交仍然是新创建的合并提交的父提交之一,因此是可访问的,而不是垃圾收集的。

事实上,在我看来,这是ours合并策略的主要用例之一;保留对一系列未进入最终产品的提交的引用。


为了说服您的团队,您可以进行合并,并在gitk等图形存储库查看器中向他们显示提交历史。如果合并的提交是可见的,那么它们将不会被垃圾收集。

所有合并都保留其所有父级。使用什么策略并不重要。

你所说的merge --squash是误导性的。当您说它不保留来自目标分支的提交时,您是对的;但是当你说";是一个"合并";。。。事实并非如此。就像快进不是合并一样。合并是指具有多个父级的提交;并不是所有的合并命令都会生成一个。

具体来说,如果您在mastergit merge --squash dev上,--squash所做的就是省略结果提交上的第二个父指针(在实际合并中,它将是指向dev的指针)。这就是为什么如果dev的提交后来成为孤立的,结果就不会保留这些提交的原因——因为生成的提交没有指向它们,它们就不是其历史的一部分。

但是,更改合并策略并不会更改父指针。在任何时候,您都可以观察到合并后的提交是历史的一部分(无论是否从中获取了任何内容),方法是在生成的分支上查看git log的输出(如果您想要更直观的表示,则可以查看gitk图);这意味着它必须被保存。

也就是说,任何ref都将保留其指向的提交的完整历史记录,而不仅仅是一个分支。在我看来,标记受影响的提交是一种更简单/不那么令人困惑的方法。也就是说,这更符合轻量级标记的用途,而不是分支的用途。(如果你反对使用标签,因为你把它们用于其他用途,并且不想打乱名称空间,你可以使用某种自定义的ref名称空间,这对我来说仍然更简单。)

例如,git merge --squash,作为;合并";,没有保留依赖关系。

这是唯一一个在成功时不保留祖先的选项,因此它是唯一一种讨论由此产生的(缺乏添加的)祖先的选项。

我的问题是,是否有一个明确的语句可以解决git merge -s ours策略的歧义。

在所有其他情况下,合并的历史记录都是合并结果的祖先。您可以通过检查文档来验证这一点。-s/--strategy选项文档没有歧义,该选项根本不会影响生成的祖先,只会影响生成内容的方式,所以它只讨论了这些。

相关内容

最新更新