解析 `svn log` 的输出以仅列出某个文件历史的先前化身的路径

Posted

技术标签:

【中文标题】解析 `svn log` 的输出以仅列出某个文件历史的先前化身的路径【英文标题】:Parse the output of `svn log` to list only the paths of previous incarnations of a certain file's history 【发布时间】:2015-07-11 18:25:36 【问题描述】:

作为一名软件开发人员,我有一个大型项目,其代码存储在 Subversion® 存储库中。多年来,我多次重构代码并将其梳理成由各种组件组成的模块化架构。一个组件已经成熟到它本身确实应该是一个独立项目的程度。

我希望该组件的代码驻留在一个新的、独立的 Subversion® 存储库中(可能会迁移到 git 存储库中)。但是,我还想保留该组件中所有文件的版本历史记录,以便我可以阅读日志和提交消息,这些消息解释了它是如何以及为什么成为当前形式的。

我创建了现有存储库的转储,并希望使用 svndumpfilter 清除转储文件中的所有提交,但可以将其导入新存储库(使用 svnadmin load)。

正如svndumpfilter documentation 倒数第二段所建议的那样,我打算使用svndumpfilter 上的include 选项来列出我希望在新存储库中保留的路径。

引用:

可能在存储库生命周期的某个时刻,您可能已将文件或目录从 svndumpfilter 排除的某个位置复制到它包含的位置。为了使转储数据自给自足,svndumpfilter 仍需要显示新路径的添加——包括由副本创建的任何文件的内容——并且不将该添加表示为来自不存在的源的副本在您过滤的转储数据流中...

...如果您怀疑您的存储库中有任何此类副本,您可能需要重新考虑您的包含/排除路径集,可能还包括作为麻烦复制操作来源的路径。

这意味着,当我们通过过滤器运行新项目时,为了保留它们的提交历史,我们不仅要include当前版本的项目文件,还要include它们祖先的路径.

问题是:我们如何确定这些祖先的路径?

可以在存储库 url 上运行 svn log 命令。这将返回其提交历史。使用 --verbose 选项可确保我们可以看到受该历史记录中任何给定提交影响的路径。

我们可以忽略文件被修改的情况。我们非常有兴趣跟踪该文件被 svn 添加到存储库时的历史记录。此外,如果该文件是使用 svn-copy(或任何有效的 svn-move)命令添加的,我们也希望追踪该“源文件”的祖先。

信息都在svn log的输出中。

--xml 选项以 xml 格式打印svn log 输出。这使机器更容易理解它。

我需要一些工具或技术来从给定存储库文件上的svn log 命令输出的 xml 流中提取相关的祖先路径数据。

如果对要提取的项目中的每个文件都执行此操作,那么我们可以构建一组路径,这些路径需要包含在运行以过滤转储文件的svndumpfilter 进程中。

这样的工具或解决方案是否已经存在?

如果是这样,如果您能告诉我,我将不胜感激。

如果不存在解决方案,我打算编写一个小命令行界面 (CLI) 程序来解析 XML。 See the project write-up on github.

除非有必要,否则我不喜欢“重新发明***”,因此感谢您的帮助。

【问题讨论】:

我最近有一个类似的要求,到目前为止我唯一能找到的是subdi.vision/extract,但我没有测试它,因为它很贵。不过可能会帮助其他人。 谢谢@ravisorg - subdi.vision/extract 功能正是我所寻找的。我想我有超过 2,000 次修订,所以还必须为高级版本付费。我可能会玩免费版本来测试它。如果是这样,我会回来报告。 【参考方案1】:
    我不知道野网中的这种工具(我想每个人都使用自己喜欢的工具“重新发明***”) 我认为,您还可以处理svn log FILENAME 的非 XML(噪音较小)输出

一些带有 HEAD 状态的(有点缺陷的)toy-repo 的样本

>svn ls -R
API/
API/intefaces.txt
Core/
Core/core-classic.txt
Modules/
Modules/modules-classic.txt

历史这么短

>svn log -v -q
------------------------------------------------------------------------
r5 | Badger | 2015-07-12 20:58:23 +0500 (Вс, 12 июл 2015)
Changed paths:
   A /trunk/API/intefaces.txt (from /trunk/inteface.txt:4)
   A /trunk/Core/core-classic.txt (from /trunk/core.txt:4)
   A /trunk/Modules/modules-classic.txt (from /trunk/modules.txt:4)
   D /trunk/core.txt
   D /trunk/inteface.txt
   D /trunk/modules.txt
------------------------------------------------------------------------
r4 | Badger | 2015-07-12 20:55:29 +0500 (Вс, 12 июл 2015)
Changed paths:
   A /trunk/API
   A /trunk/Core
   A /trunk/Modules
------------------------------------------------------------------------
r3 | Badger | 2015-07-12 20:53:36 +0500 (Вс, 12 июл 2015)
Changed paths:
   D /trunk/a.txt
   D /trunk/b.txt
   D /trunk/c.txt
   A /trunk/core.txt (from /trunk/a.txt:2)
   A /trunk/inteface.txt (from /trunk/c.txt:2)
   A /trunk/modules.txt (from /trunk/b.txt:2)
------------------------------------------------------------------------
r2 | Badger | 2015-07-12 20:50:40 +0500 (Вс, 12 июл 2015)
Changed paths:
   A /trunk/a.txt
   A /trunk/b.txt
   A /trunk/c.txt
------------------------------------------------------------------------
r1 | Badger | 2015-07-12 20:47:11 +0500 (Вс, 12 июл 2015)
Changed paths:
   A /branches
   A /tags
   A /trunk
------------------------------------------------------------------------

如果要恢复 f.e. 的历史记录Core dir 对于 XML 和非 XML 日志,您必须执行大致相同数量的操作

>svn log Core -q -v | grep A | grep Core | grep from
   A /trunk/Core/core-classic.txt (from /trunk/core.txt:4)

(递归地对“from”侧的每个 PATH 部分重复)

或者,对于 XML 日志(日志的无关部分被修剪)

>svn log Core -q -v --xml
...
<paths>
...
<path
   text-mods="false"
   kind="file"
   copyfrom-path="/trunk/core.txt"
   copyfrom-rev="4"
   action="A"
   prop-mods="false">/trunk/Core/core-classic.txt</path>
...

(解析每个路径节点以获得有趣的路径,从copyfrom-path键中提取源路径,使用新提取的路径重复记录)

【讨论】:

谢谢。这是一些非常有用的信息。

以上是关于解析 `svn log` 的输出以仅列出某个文件历史的先前化身的路径的主要内容,如果未能解决你的问题,请参考以下文章

使用 Bash 解析 ifconfig 以仅获取我的 IP 地址

Log4j 配置某个类中某个方法的输出日志到指定文件

log4j怎么把某个类中的日志单独输出到一个文件?

linux中如何将运行某个脚本的输出记录到log.log呢.

Linux如何列出svn一个文件夹下的所有文件

什么svn责备相当于clearcase?