Mercurial:每个文件的最新更改

Mercurial: Most recent change per file

我正在寻找一种方法来使 Mercurial 输出像这样 table:

File        Most recent revision changing the file          Date of that revision
====        ======================================          =====================
foo.py      44159adb0312                                    2018-09-16 12:24
...         ...                                             ...

这就像 github 在 "Code" 概览页面上所做的一样。 (截图来自 torvalds/linux):

"Most recent" 可以引用日期或相对于当前变更集或当前分支的 DAG 层次结构。也许后者更有用,但在我的特定用例中,它没有什么不同。

我还希望能够提供我想要 table 的文件列表或子目录。 (我不一定想要所有东西)

我知道我可以使用一个小脚本来完成它,循环遍历 hg log -l 1 <file>,但我想知道是否有更有效/更自然的解决方案。

更有效/更自然的解决方案可以是:

  • 为所需的日志输出创建模板|样式(我无法预测,哪种方式对您来说更好
  • hg log -l 1 --template ...hg log -l 1 --style ...
  • 创建别名

编辑

很多之后,更正确的解决方案(来自 hg grep

hg grep "." "set:**.py" --files-with-matches -d -q -T"{files % '{file} {date|age}\n'}"

test-repo 中的部分输出

hggit/__init__.py 7 weeks ago
hggit/git_handler.py 7 weeks ago
hggit/gitdirstate.py 7 weeks ago
…

您必须修改文件集才能仅获得树的一部分(所有分支)的结果,并且可能需要修改模板才能满足您的需求。

我刚才没有用于选择“分支 X 中的文件”的文件集,我认为它将使用 revs() 谓词

"revs(revs, pattern)"

Evaluate set in the specified revisions. If the revset match multiple revs, this will return file matching pattern in any of the revision.

因为一些未发布的谓词(根据例子,参考工作目录见@"set:revs('wdir()'...")可用于定义 revset 但我不能 discover/predict 分支谓词的正确形式

Git 将跟随提交 DAG,因为它仅此而已。在 Mercurial 中,你有(很多)更多的选择,因为你有更多的数据。

这里的理想选择可能是 follow(file, .)(根据需要结合 firstlast)。但正如 hg help revset 会告诉您的那样,您有以下选项(我已将列表缩小到明显适用的选项):

  • ancestors(set[, depth])

    将此与 set 一起使用 . 以获取当前提交的祖先,例如,如果您想执行 DAG-following a la Git。或者,使用::.,基本相同

  • branch(string or set)

    将此与 . 一起使用可获取当前分支中的所有提交。结合其他限制器(例如,parents)以避免在您不在当前分支的尖端时查看当前分支中的后续提交。

  • file(pattern)

    将其与 glob 模式结合使用以查找影响给定文件的变更集。

  • filelog(pattern)

    file 相似,但速度更快,牺牲了一些准确性以换取速度(有关详细信息,请参阅文档)。

  • follow([file[, startrev]])

    引用文档:

    An alias for "::." (ancestors of the working directory's first parent). If file pattern is specified, the histories of files matching given pattern in the revision given by startrev are followed, including copies.

  • modifies(pattern)

    使用它(使用任何模式,而不仅仅是 glob)来查找修改某些文件或目录的变更集。我认为这仅限于 M 类型的修改,而不是文件的添加或删除,因为还有 adds(pattern)removes(pattern)。一起使用所有三个 or-ed 来查找任何 add/modify/remove 操作。

  • first(set, [n])
    last(set, [n])
    limit(set[, n[, offset]])

    使用它从 revset 中提取特定条目。

向前搜索时(默认),last(follow(file, .)) 似乎可以很好地找到正确的修订版。正如您所指出的,您必须为每个文件执行一次此操作——如果您编写自己的 Mercurial 插件来执行此操作而无需始终重新加载系统的其余部分,它肯定会更快。

您无法绕过所有文件的循环。然而,使用 hg manifest 您可以获得该文件列表。然后根据需要模板化输出:

for f in $(hg ma); do hg log -l1 $f -T"$f\t\t{rev}:{node|short}\t\t{date|isodate}"; done

这样的输出类似于

.hgignore               38289:f9c426385853              2018-06-09 13:34 +0900
.hgsigs         38289:f9c426385853              2018-06-09 13:34 +0900
.hgtags         38289:f9c426385853              2018-06-09 13:34 +0900

您可能想要更多地了解输出格式。有关输出模板的完整概述,请参阅 mercurial wiki