40

我正在研究一种新的基于weave的数据结构来存储版本控制历史。这无疑会在它问世时引发一些关于它是否是正确的做事方式的宗教战争,但这不是我现在的问题。

我的问题与输出责备有关应该给。当一行代码被多次添加、删除和合并到自身中时,并不总是清楚应该归咎于哪个修订版本。值得注意的是,这意味着当一段代码被删除时,它曾经存在的所有记录都消失了,删除没有责任。与我讨论过这个问题的每个人都说,试图做得更好根本不值得。有时人们会说,被删除的部分后面的那一行的责任从它实际上是什么变成了该部分被删除时的修订。据推测,如果该部分位于末尾,那么最后一行的责任就改变了,如果文件最终为空,那么责任确实会消失在以太中,因为实际上没有地方可以放置责任信息。

继续我的实际问题。通常要为每一行负责,您会查看在历史记录中添加和删除它的完整历史记录,并使用三向合并(或者,在交叉合并的情况下,随机胡说八道)并基于这些之间的关系您根据其历史确定该行是否应该存在,如果不应该存在,那么您将其标记为当前版本的新版本。如果一行出现在具有不同责任的多个祖先中,那么它会任意选择继承哪一个。同样,我认为继续这种完全没有记录但事实上的标准做法将是没有争议的。

我的新系统的不同之处在于,它不是基于对整个历史的复杂计算来对给定行是否应该在当前修订版中进行复杂计算,而是简单地查看直接祖先,以及该行是否在任何他们选择任意一个来继承责任。我之所以做出这个改变主要是出于技术原因(出于类似的技术原因和缺乏关心,其他责备实现完全有可能做同样的事情)但在考虑了一下之后,我的一部分实际上更喜欢新行为比旧的更直观和可预测。大家怎么看?

4

3 回答 3

35

实际上,我在那里写了一个责备实现(我相信Subversion的当前实现,除非有人在过去一两年内更换了它)。我也帮助了其他一些人。

至少责备的大多数实现都没有按照您的描述进行:

通常要为每一行负责,您会查看在历史记录中添加和删除它的完整历史记录,并使用三向合并(或者,在交叉合并的情况下,随机废话)并基于您之间的关系根据其历史确定该行是否应该存在,如果不应该存在,那么您将其标记为当前版本的新版本。如果一行出现在具有不同责任的多个祖先中,那么它会任意选择继承哪一个。同样,我认为继续这种完全没有记录但事实上的标准做法将是没有争议的。

实际上,大多数责备都比这复杂得多,并且根本不费心尝试使用关系,但他们只是使用简单的 delta 结构(通常是相同的内部结构,无论他们以前使用什么 diff 算法)以任意顺序引导父母它将其转换为文本输出)以查看块是否已更改,如果是,则归咎于它,并将该行标记为已完成。

例如,Mercurial只是进行迭代深度优先搜索,直到所有行都被指责。它没有试图考虑这些关系是否使它不太可能责怪正确的人。

Git确实做了一些更复杂的事情,但仍然不像你描述的那样。

Subversion 做了 Mercurial 做的事情,但是历史图非常简单,所以更容易。

反过来,您的建议实际上是他们所有人真正在做的事情:

选择一个任意祖先,然后沿着兔子洞的那条路走,直到完成,如果它没有导致你责备所有行,任意选择下一个祖先,继续直到分配所有责备。

于 2012-12-29T04:32:54.493 回答
11

在个人层面上,我更喜欢您的简化选项。

原因:不管怎样,责备的使用并不多。

所以我认为浪费大量时间来全面实施它没有任何意义。

这是真的。责任在很大程度上被证明是那些“彩虹尽头的金罐”特征之一。从我们这些站在地上的人看来,这真的很酷,梦想着有一天我们可以点击一个文件,看看谁写了哪几行代码。但是现在它已经被广泛实施,我们大多数人已经意识到它实际上并不是很有帮助。在 Stack Overflow上检查blame标签上的活动。它是荒凉的。

仅在最近几个月里,我就遇到了几十个“值得指责”的场景,在大多数情况下,我都尝试先使用指责,发现它要么很麻烦,要么完全没有帮助。相反,我通过对有问题的文件进行简单的过滤更改日志来找到我需要的信息。在某些情况下,如果我坚持不懈,我也可以使用 Blame 找到信息,但它会花费更长的时间。

主要问题是代码格式更改。几乎所有的第一层怪都被列为……我!为什么?因为我是负责修复换行符和制表符、重新排序函数顺序、将函数拆分为单独的实用程序模块、修复注释拼写错误以及改进或简化代码流的人。如果不是我,其他人也在沿途某处做了空格或块移动。为了在没有责备的帮助下我还记得之前的任何事情上得到有意义的责备,我不得不回滚修订并重新责备。并再次责备。然后再次。

因此,为了让责备在最幸运的情况下真正节省时间,责备必须能够启发式地越过换行符、空格,并理想地阻止复制/移动更改。这听起来是一个非常艰巨的任务,尤其是在为单个文件搜索变更日志时,大多数情况下,无论如何它不会产生很多差异,您可以相当快地手动筛选。(值得注意的例外可能是,设计糟糕的源代码树,其中 90% 的代码被塞进一两个巨大的文件中……但是如今在协作编码环境中,谁会再做很多事情了?)。

结论:给它一个简单的责备实现,因为有些人喜欢看到“它可以责备!” 在功能列表中。然后继续做重要的事情。享受!

于 2012-12-29T04:24:10.333 回答
0

行合并算法比开发人员更愚蠢。如果他们不同意,那只是表明合并是错误的,而不是表明一个决策点。所以,简化的逻辑实际上应该更正确。

于 2012-12-29T05:35:08.540 回答