“git log --pretty=〈pretty format>”是一个瓷器命令还是管道命令?

csga3l58  于 2023-03-16  发布在  Git
关注(0)|答案(4)|浏览(180)

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

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

我想知道这个命令的输出是适合程序解析(plumbing)还是只适合呈现给人(ceramine),例如,在一些项目中,我使用以下命令获取commit SHA + author name + commit summary:

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

然后用换行符分割输出字符串(我使用的是Linux)。
除此之外,在某些情况下我还会做这样的事情:

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

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

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

这是一种好的方法吗?如果不是,那么通过编程获取提交信息的首选方法是什么?

mv1qrgav

mv1qrgav1#

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来阅读它--包含了将命令分解为陶瓷层和管道层的内容。

bqjvbblv

bqjvbblv2#

我同意kostix;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 * 是否像 * 一个plumbing命令一样工作。这需要枚举所有的git log配置选项。不幸的是,没有一个干净的方法来做到这一点--可以随时添加更多的选项,有些选项是随着时间的推移而添加的。
这是我在git loggit config手册中找到的一个列表,注意我省略了所有面向差异的提交(例如上面提到的color.diffdiff.*项),因为在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的plumbing variant *,或者一个git format-log-metadata plumbing命令,接受--pretty=<directives>选项并格式化日志元数据。因为它没有,所以需要git log --pretty=format:...输出的脚本的编写者来确保他们知道可能影响他们的配置选项。

nfs0ujit

nfs0ujit3#

感谢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用于新行(lol...)

是的,虽然格式说明符如%ad%cN可能会受到用户设置的影响,但上面的说明符不太可能。因此,我认为我当前的代码是安全的,不容易出错,该代码使用上面说明符组合的漂亮格式解析git log的输出。

fd3cxomn

fd3cxomn4#

仅添加到kostix's answer:对于我来说,git show-ref -s HEAD不输出任何内容,返回退出代码1。
取代:

git cat-file commit `git show-ref -s HEAD`

我用途:

git cat-file commit `git show-ref --head -s HEAD`

或:

git cat-file commit `git rev-parse HEAD`

相关问题