【问题标题】:Is "git log --pretty=<pretty format>" a porcelain or plumbing command?“git log --pretty=<pretty format>” 是瓷器还是管道命令?
【发布时间】:2018-12-02 15:33:24
【问题描述】:

我正在创建一些用于获取提交信息的脚本和程序

git log --pretty=<my format> -1 <commit>

我想知道这个命令的输出是否适合由程序(管道)解析或仅用于呈现给人类(瓷器)。例如,在某些项目中,我使用以下方式获取提交 SHA + 作者姓名 + 提交摘要:

git log --pretty="%H%n%an%n%s" -1 HEAD

然后我用换行符分割输出字符串(我在 Linux 上)。

此外,在某些情况下,我还会这样做:

git log --pretty='[%h] %an: %s' -1 HEAD

然后使用以下正则表达式解析结果,期望在捕获的组中包含简短的 SHA、作者姓名和提交摘要:

^\[(\w+)\] ([^:]+): (.*)$

这是一个好方法吗?如果不是,以编程方式获取有关提交的信息的首选方法是什么?

【问题讨论】:

  • 我更喜欢它是一个瓷器命令,因为这个(离题)线索:在 Pro Git v2 中,Chapter 10.1 说“本书的前九章几乎专门处理瓷器命令”,并且@ 987654327@,面向机器的格式,在“本书前九章”中提到了in Chapter 2.3

标签: git git-log


【解决方案1】:

git log 是一个瓷器命令。

它实际上执行了相当多的任务——结合遍历修订图,git diffgit grep 等等。

做某事的管道方式

git log --pretty='[%h] %an: %s' -1 HEAD

是将git show-refgit cat-file 结合起来并解析结果——类似于

git cat-file commit `git show-ref -s HEAD` |
  while read line; do
    # do some processing
  done

实际上是根 Git 的手册页,git(1)——运行 git help git 来阅读它——包含将命令分解为瓷层和管道层的内容。

【讨论】:

  • git cat-file commit &lt;ref&gt; 似乎是一个可靠的管道命令,但输出似乎比git log --pretty 更难解析。有更好的解决方案吗?
  • 我看不出它有什么复杂之处:它是格式为 ^key SP value LF$ 的行的标题,由内容中的空行 ^LF LF$ 分隔。所以基本上你阅读所有的行,直到一个空行,然后寻找特定的关键字,例如author 和/或committer。我的意思是,你能详细说明你在这方面遇到了什么特别的困难吗?
  • 你好,你能看看我自己的答案,并给一些cmets吗? (+1 为您的回答)
【解决方案2】:

我同意kostixgit log 是一个瓷器命令。但这里的问题是,git log 可以做一些其他命令很难做到的事情,所以我们有时可以让git log 一个管道命令。

当比较时,管道和瓷器之间的主要区别就会出现,例如,git branchgit taggit for-each-ref,或 git diffgit diff-treegit diff-filesgit diff-index。这不是每个管道有多少瓷器。例如,管道git for-each-ref 有两个独立的陶瓷前端,而单个前端git diff 有三个管道后端。不,关键是git diff 会根据用户选择的配置项改变其行为

diff.algorithm
diff.dirstat
diff.renameLimit
diff.renames
diff.statGraphWidth
diff.submodule

等等。管道版本忽略所有用户配置,因此您编写的脚本对 Alice、Bob、Carol 和 Dave 的行为相同,即使他们有不同的设置。

当使用这个定义时,我们可以决定git log 是否像一个管道命令。这需要枚举所有git log 配置选项。不幸的是,没有干净的方法可以做到这一点 - 可以随时添加更多选项,并且随着时间的推移添加了一些选项。

这是我通过查阅git loggit config 手册找到的列表。请注意,我省略了所有面向差异的那些(例如,color.diff 和上面提到的diff.* 项目),因为有管道命令来处理git log 中的-p 等效项(尽管您必须完成一次提交一次)。

color.decorate.<slot>
core.notesRef
format.pretty
i18n.logOutputEncoding
log.abbrevCommit
log.date
log.decorate
log.follow
log.graphColors
log.mailmap
log.showRoot
log.showSignature
notes.displayRef
pretty.<name>

所以,假设我们想从某个特定的提交中获取提交者的日期,并以某种特定的方式格式化。为此,我们可能会运行:

git log --no-walk --pretty=format:%cd

我们在git log 的主要文档中发现,%cd 的漂亮格式是这样描述的:

%cd:提交者日期(格式尊重 --date= 选项)

我们未能提供--date= 选项,因此git log 将查找log.date 设置。这是一个用户配置选项,我们的git log 输出将取决于用户的选择,而不是我们的选择。

要使这个git log 一个管道命令,我们必须覆盖log.date 配置设置,例如--date=default-c log.date=default

git -c log.date=default log --no-walk --pretty=format:%cd

或:

git log --no-walk --date=default --pretty=format:%cd

理想情况下,Git 应该有一个 plog 命令定义为 git log 的管道变体,或者一个 git format-log-metadata 管道命令接受 --pretty=&lt;directives&gt; 选项并格式化日志元数据。既然没有,任何人都可以编写脚本,需要git log --pretty=format:... 输出,以确保他们知道可能影响他们的配置选项。

【讨论】:

  • 这是否意味着,即使它不是严格意义上的管道命令,我仍然可以覆盖相关设置并期待管道结果?
  • @iBug:是的。问题是,在未来,因为git log 真的是瓷器,有人可能添加一个新的配置项,你还不能告诉你必须重写,因为现在你不需要覆盖它。
  • 你好,你能看看我自己的回答,给一些cmets吗? (+1 为您的回答)
【解决方案3】:

感谢 kostic 和 torek 的回答。

尽管他们回答了,我相信 一些 漂亮的格式选项可以安全地被视为管道(即安全地被程序解析)。例子包括

  • %H 用于完全提交 SHA
  • %T 用于全树 SHA
  • %P 用于完整的父 SHA
  • %an%cn%ae%ce%at%ct 用于作者/提交者姓名/电子邮件/日期(Unix)。 RFC 2822 和 ISO 8601 样式时间也是可靠的%aD%cD%aI%cI
  • %s 提交摘要
  • %G? 获取签名状态
  • %n 换行(哈哈...)

是的,虽然%ad%cN 等格式说明符会受到用户设置的影响,但上述说明符不太可能。所以我决定,我当前的代码解析git log 的输出并结合了上述说明符的漂亮格式,是安全且不易出错的。

【讨论】:

  • @jthill 和git log有什么不同?
  • 它有核心命令又名管道保证,它的输出供您使用。
  • 将这些指令与--pretty={,t}format / --format= 一起使用似乎很安全,是的。奇怪的是,虽然这些大部分都可以与git rev-list 一起使用,但它们并没有被列为它的选项。但是 rev-list 和 log 是从同一个源文件构建的,并且主要处理相同的参数。不幸的是,git rev-list--formats 一起使用时表现不佳!
  • @torek 你能详细说明最后一句话吗?我很好奇 git rev-list 在漂亮的格式下表现不佳。
  • 试试吧:git log --pretty=format:"%H %cn" HEAD vs git rev-list --pretty=format:"%H %cn" HEAD。当然,你可以扔掉所有其他的行,但你为什么要必须这样做呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-06
  • 1970-01-01
  • 2017-02-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
相关资源
最近更新 更多