"git log --pretty=<pretty format>" 是陶瓷命令还是管道命令?

Is "git log --pretty=<pretty format>" a porcelain or plumbing command?

我正在创建一些使用

获取提交信息的脚本和程序
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+)\] ([^:]+): (.*)$

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

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 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: committer date (format respects --date= option)

我们未能提供 --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=<directives> 选项并格式化日志元数据。既然没有,这取决于任何编写脚本的人,需要 git log --pretty=format:... 输出,以确保他们知道可能影响他们的配置选项。

感谢 kostic 和 torek 的回答。

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

  • %H 完全提交 SHA
  • %T 完整树 SHA
  • %P 对于完整的父 SHA
  • %an, %cn, %ae, %ce, %at, %ct for author/committer name/email/date(Unix)。 RFC 2822 和 ISO 8601 样式时间也是可靠的 %aD%cD%aI%cI
  • %s 用于提交摘要
  • %G? 签名状态
  • %n换行(哈哈...)

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