【问题标题】:Is there a way in RCS or SCCS, etc to 're-origin' the changes?在 RCS 或 SCCS 等中有没有办法“重新启动”这些更改?
【发布时间】:2018-03-10 15:51:33
【问题描述】:

我目前使用 SCCS 进行源代码控制,但这个问题一般适用于版本控制系统。

为了确定一段代码的起源时间,我有时会打开 SCCS 。文件来查找并将代码周围的插入命令与版本标头匹配。当然,一段时间后,这些文件变得很难以这种方式阅读。

有没有办法“重新生成”一个 SCCS 文件,以便第一个存储的版本是 5 年前的任何版本 - 并且只有从那时起的那些 deltas 被保留?我想这可以通过检查你想要的每个版本并将它们重新增量到一个新的 repo 来完成,但是必须有人自动化了这个过程,不是吗?

或者,更好的是(?),是否有一个实用程序可以显示带有与每一行关联的版本 # 注释的文件的当前版本?我刚刚在 bitkeeper 中看到了一个“注释”命令的文档。我要问的就是这种事情。哎呀。我看到“sccs get -m”命令可以做到这一点(实际上我的 sccs 包装脚本中有一个选项可以做到这一点)。对不起 - 真是个笨蛋。

不过,第一个“重新起源”问题仍然存在......

【问题讨论】:

    标签: git version-control cvs rcs


    【解决方案1】:

    您将一些单独的概念混合在一起(正如您在 annotate 子命令中发现的那样)。注释(git annotatesvn annotate 等)或有时称为“责备”要求 VCS 向您显示有关源本身具有该特定源片段的最早修订的信息——通常是一行,因为我们主要处理“代码行”——与在一个特定版本中的形式相同。

    但这不是您仍在寻找的内容,所以让我们深入研究。所有版本控制系统都有一个问题:如果您要存储每个文件的每个版本,则可能需要大量存储空间。

    因此,大多数 VCS 使用某种压缩方式,并且大多数会立即直接使用 delta encoding,也称为 delta 压缩: 完整地存储一个版本,而不是完整地存储第二个版本,只存储一组指令,可用于修改存储的完整版本以获得第二个版本。

    对多个版本重复此操作,您将获得链式增量,您可以从某个初始版本开始并反复对其进行修改以获得最终版本。最初,SCCS 将其用于“正向”方向:存储初始版本,然后将对其的第一个更改存储为第二个版本,然后将第二个版本的更改存储为第三个版本,依此类推。显然,这有点慢。因此,RCS 使用 reverse deltas:原封不动地存储最新版本,同时存储 deltas 以计算其后续版本的早期版本。这使得检索最新版本很快,而最旧版本很慢——通常是人们想要的——但它有一个不同的缺点:它不能与分支一起正常工作。因此,RCS 实际上在其主干上使用反向增量,在其分支上使用前向增量。

    由于 CVS 是(或曾经)基于 RCS 文件格式构建的,它也使用这种反向但也正向的增量存储格式。

    为了提高性能,现代 SCCS 使用称为 interleaved deltas 的概念,存储库存储相当于所有版本联合的内容。通过存储文件的线性传递足以提取任何特定版本。 (链接的 Wikipedia 页面说 Bitkeeper 也使用交错增量。)

    我个人不知道 Subversion 在内部使用什么,但How exactly does subversion store files in the repository? 建议它使用反向增量和快照。烘焙快照(另一个“完全完整”的版本)时不时地提供了一种设置要应用的增量数量限制的方法。

    Git 做了一些完全不同的事情。 Git 不是单独存储每个文件并针对该文件的先前版本进行增量压缩,而是存储它称为 objects 的内容。每个对象至少在逻辑上是独立的(快照)——因此任何文件的任何版本都不会被增量压缩,尽管每个快照都是 zlib 压缩的。为了节省额外的空间,Git 偶尔会将多个对象压缩到一个“包文件”中,而这里的包文件内部对象 确实 被 delta-compressed ... 但针对 任何其他对象 em>,而不仅仅是代表同一个源文件的那些。 (特别是这允许 Git 使用其他树对象来压缩树对象。)

    最后,这对 Git 意味着它使用 delta 压缩,可能在任何方向上——这可能混合正向和反向——使用快照来限制链长度(--depthpack.depth),但是对象与对象的关系,不一定只是一个文件与同一文件的另一个版本。出于实际目的,Git 不会完全随意选择这些对象(很难知道哪些对象会与其他对象一起很好地压缩),而是根据对象类型、对象大小、在树对象中找到的文件名以及年龄(我不确定它从哪里得到这些年龄),所以 Git 经常以相当于反向增量的结果结束,但不能保证。 (Git 还会重用之前包中预先计算的 delta 链,除非您告诉它不要这样做;请参阅 --no-reuse-delta aka -f。)

    作为一般规则,没有办法告诉修订系统完全修改其内部存储格式。一些 VCS 可能有例外。例如,Git 有点不寻常,因为 git repack 正是这样做的,但对您的特定用例没有用处!

    【讨论】:

      【解决方案2】:

      (我想知道你到底为什么要使用 SCCS。)

      此类命令因不同的源代码控制系统而异。 SCCS 确实很古老,不太可能有这样的命令。

      在 RCS(它也很古老,但比 SCCS 稍微现代一点)中,您可以使用“-o”选项来删除(“过时”)文件的旧版本。例如,如果您有一个存储修订版 1.1、1.2、1.3、...的文件,那么您可以使用

      rcs -o1.1 filename
      

      从历史记录中删除版本 1.1,或

      rcs -o1.1:1.3
      

      删除修订版 1.1、1.2 和 1.3。

      是否有一个实用程序可以显示文件的当前版本,并用与每一行关联的版本 # 进行注释

      对于大多数现代系统,是的:

      • CVS:cvs annotate filename
      • SVN:svn blame filename(还有praiseannotateann
      • Git:git blame filename
      • Mercurial:hg annotatehg blame

      我不相信 SCCS 或 RCS 有这样的命令。将 RCS 文件导入 CVS 很容易(只需将 filename,v 复制到 CVS 存储库中),并且可能有自动化工具可以将 SCCS 存储库转换为 RCS 存储库。

      这些命令显示文件当前版本的逐行注释,这意味着它们不会为您提供有关已删除行的任何信息。为此,您可以使用一些类似 diff 的命令来比较指定的版本(rcsdiffcvs diffsvn diffgit diffhg diff)。

      【讨论】:

      • 我认为那些“删除版本”选项也删除了相关的更改。这不是真的吗。我想保留当前版本中的所有内容,只是忘记它是如何到达那里的古老历史。
      • 使用 SCCS,因为我们在 AIX 上,这就是我们在 80 年代开始编写系统时的情况。我有一些不错的脚本,它们包含 SCCS 命令,使其易于在项目中使用,根据我们一直在工作的方式量身定制 - 迁移似乎总是太难了。但是,是的,我们是恐龙.. ;-)
      • @littlenoodles:我不太清楚您所说的“删除相关更改”是什么意思。如果您的存储库中有修订版 1.1、1.2、1.3 和 1.4,那么rcs -o1.1:1.2 将为您留下修订版 1.3 和 1.4——它们将与命令之前的内容保持一致。你只会失去旧的历史。我建议您创建一个小型测试存储库来验证这一点。
      • 哦,那它确实按照我的要求做。文档不够清晰 - 或者我太密集而无法获得它。它读起来就像“撤消那组更改”——但实际上谁会想要这样做。不过,感谢您的澄清。
      猜你喜欢
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 2020-06-26
      相关资源
      最近更新 更多