从 python 子进程调用 git-log 时选项 --decorate-refs 被忽略
option --decorate-refs is ignored when calling git-log from python subprocess
我被这个错误困住了。我试图搜索一堆东西,我尝试使用调试器跟踪调用。我none更聪明。
我的问题:
我从命令行运行这个命令
git log --format=format:%D --simplify-by-decoration --decorate-refs=*platVer*
我得到了预期的标签列表
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123
tag: platVer-20.07.000
tag: platVer-20.06.000
tag: platVer-20.05.000
如果我在命令行上从python运行这个,我也会得到预期的列表
>>> from subprocess import call, Popen, PIPE
>>> pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'])
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123
tag: platVer-20.07.000
tag: platVer-20.06.000
tag: platVer-20.05.000
运行 此行在空闲或脚本中未捕获输出(如预期),要启用标准输出的捕获,popen 需要将标准输出参数设置为 PIPE。
但是如果我 运行 使用 stdout=PIPE,它似乎会忽略 '--decorate-refs=*platVer*'
并且只列出整组 refs
>>> pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'], stdout=PIPE)
>>> pp.stdout.read()
b'HEAD -> feature/ps2python, origin/feature/ps2python\ntag: platVer/222.3.4123, tag: myplatVer-222.3.4123, tag: mao_test ....
当我从脚本或空闲时 运行 得到同样的结果。
from subprocess import Popen, PIPE
pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'], stdout=PIPE)
print( pp.stdout.read().decode('ascii' ) )
给我这个
HEAD -> feature/ps2python, origin/feature/ps2python
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123, tag: mao_test
show-current, develop
tag: platVer-20.07.000,
... (cut the remaining many many lines of refs)
我正在 运行宁 windows 10(版本 10.0.18363.778)
git 版本 2.29.2.windows.2
python 版本 3.8.5
我试过 shell=Tre/False, universal_newlines=True/False
我在 WSL 中试过了 (ubuntu)
都给出了相同的结果
然后我在虚拟 ubuntu 18.LTS 中尝试了。使用 git 版本 2.17。在这里我得到了有线结果,其中 '--decorate-refs=*platVer*'
被忽略了。从命令行。
然后我在这个 ubuntu 上将 git 更新到较新的版本 (2.29.2)。现在命令完全按预期工作....
然后我尝试了来自 python 的相同命令,结果与在 win10 机器上相同。
请帮忙。无法弄清楚设置 stdout=PIPE
如何改变 git 命令的行为。
编辑:
我确实检查过使用和不使用 PIPE
时调用的 git 版本相同
编辑2:
我将@torek 的回答标记为已接受,因为它完美地解决了我的问题。
不过,我应该说明我使用 git-log 的目的是为了获得更广泛的答案。
My goal is to find the tag that is the first tag found when traveling
back in history (topological or graph ordering) and that matches a
regular expression.
我以前使用过 rev-list,但没有发现任何文档表明这会按我想要的顺序传送标签,也许我错过了什么。
当我同时声明我需要正则表达式匹配时,我在我的命令中使用简单的 glob 模式的原因是我假设 globbing 更快,因此将它用作预过滤器以缩短python中需要正则表达式解析的列表。我希望标签列表在几年内包含 1000 多个标签并且还在增长。其中带有单词 'platVer' 的标签将占该列表的 1% 左右。
将 --decorate=full
或 --decorate=short
添加到您的 git log
参数中。您也可以使用 --decorate=true
或 --decorate=1
,但现在 full
和 short
是记录值。完整包括全名(例如,refs/heads/somebranch
),而 short
缩写为分支或标签名称。
很长(但可选)有用的背景信息
默认的 log.decorate
设置是 auto
(从 Git 2.9 开始;之前是 no
/0
/false
, 并且在不同的地方引入了各种错误,然后在以后的版本中修复;它自 Git 2.13) 以来一直稳定。 auto
设置意味着 short
如果人类正在读取输出,no
如果程序正在读取输出 .1
--simplify-by-decoration --decorate-refs=...
需要装饰本身(即必须打开)才能工作。可能这些选项中的任何一个都应该暗示 --decorate=short
如果它目前仍然 auto
在 Git 配置中未设置。2
这一切都指向以编程方式使用 git log
的更普遍的问题,例如,从 Python 和 subprocess
:git log
是 Git 调用的内容porcelain命令,这意味着它服从用户配置。如果用户有 log.decorate
设置,它将覆盖任何默认值。现在您了解了 log.decorate
和 --decorate=
参数,您可以使用 --decorate=
参数(它会覆盖任何用户配置)在程序中强制执行正确的行为。但是 other 用户可配置的项目存在于 git log
中会破坏你的程序吗? Git 的未来版本,其中 git log
可能会获取新的配置项?不幸的是,今天 你 对这个更普遍的问题无能为力,但由于 git log
所做的某些事情不能由任何所谓的 [=83] =]plumbing 命令——这些命令 不会 根据用户配置更改行为,因此对于其他程序很有用,因为它们具有已知的固定输出格式—git log
需要一个选项来让它表现良好。 (git status
命令对此有 --porcelain
选项;git log
只需要它自己的版本。)
1Git 实际上 不知道 是否有人正在阅读输出。相反,它通过检查标准输出流来近似:如果标准输出(文件描述符 1)响应 isatty
C 库调用的真值,或者 git log
输出被馈送到寻呼机,它假设一个人正在阅读输出。在 subprocess
中使用管道意味着 stdout 是 而不是 tty,默认情况下它也会禁用寻呼机。但是,有一个强制使用寻呼机的用户配置设置:请参阅“更一般的问题”段落。
2一般来说,Git配置的工作方式是这样的:
首先,程序设置任何自动默认值,例如log.decorate=auto
(这通常只是开放编码,而不是使用配置机制)。
接下来,Git读取系统配置文件。如果其中有 log.decorate=short
之类的设置,则应用该设置,覆盖自动默认值。 (这通常通过回调,从配置机制到程序。)
接下来,Git读取您的个人全局配置文件。如果其中有 log.decorate=auto
等设置,则应用该设置。如果之前的配置有设置,这将覆盖之前的设置。
接下来,Git 读取此特定 Git 存储库的配置文件。如果它有诸如 log.decorate=full
之类的设置,则应用该设置,并像以前一样覆盖任何以前的设置。
最后,Git 应用命令行参数设置。因此,这些会覆盖在前面任何步骤中选择的任何设置。
例如,您可以这样安排 user.name
and/or user.email
对于一个特定的 Git 存储库来说是不同的。您在全局配置中设置这些,Git 在读取每个存储库配置之前读取;然后在每个存储库配置中将它们设置为不同的值,并覆盖全局配置。
在 Git 的较新版本中,您还可以设置 每个工作树配置: git config --worktree
。这是在每个存储库配置文件之后读取的,但在命令行参数之前使用,因此它具有第二高的优先级。要使每个工作树设置生效,您必须启用 extensions.worktreeConfig
。在这里要小心,因为这个扩展有一段时间存在一些错误。
我被这个错误困住了。我试图搜索一堆东西,我尝试使用调试器跟踪调用。我none更聪明。
我的问题:
我从命令行运行这个命令
git log --format=format:%D --simplify-by-decoration --decorate-refs=*platVer*
我得到了预期的标签列表
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123
tag: platVer-20.07.000
tag: platVer-20.06.000
tag: platVer-20.05.000
如果我在命令行上从python运行这个,我也会得到预期的列表
>>> from subprocess import call, Popen, PIPE
>>> pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'])
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123
tag: platVer-20.07.000
tag: platVer-20.06.000
tag: platVer-20.05.000
运行 此行在空闲或脚本中未捕获输出(如预期),要启用标准输出的捕获,popen 需要将标准输出参数设置为 PIPE。
但是如果我 运行 使用 stdout=PIPE,它似乎会忽略 '--decorate-refs=*platVer*'
并且只列出整组 refs
>>> pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'], stdout=PIPE)
>>> pp.stdout.read()
b'HEAD -> feature/ps2python, origin/feature/ps2python\ntag: platVer/222.3.4123, tag: myplatVer-222.3.4123, tag: mao_test ....
当我从脚本或空闲时 运行 得到同样的结果。
from subprocess import Popen, PIPE
pp = Popen(['git', 'log', '--decorate-refs=*platVer*', '--format=format:%D', '--simplify-by-decoration'], stdout=PIPE)
print( pp.stdout.read().decode('ascii' ) )
给我这个
HEAD -> feature/ps2python, origin/feature/ps2python
tag: platVer/222.3.4123, tag: myplatVer-222.3.4123, tag: mao_test
show-current, develop
tag: platVer-20.07.000,
... (cut the remaining many many lines of refs)
我正在 运行宁 windows 10(版本 10.0.18363.778) git 版本 2.29.2.windows.2 python 版本 3.8.5
我试过 shell=Tre/False, universal_newlines=True/False 我在 WSL 中试过了 (ubuntu) 都给出了相同的结果
然后我在虚拟 ubuntu 18.LTS 中尝试了。使用 git 版本 2.17。在这里我得到了有线结果,其中 '--decorate-refs=*platVer*'
被忽略了。从命令行。
然后我在这个 ubuntu 上将 git 更新到较新的版本 (2.29.2)。现在命令完全按预期工作....
然后我尝试了来自 python 的相同命令,结果与在 win10 机器上相同。
请帮忙。无法弄清楚设置 stdout=PIPE
如何改变 git 命令的行为。
编辑: 我确实检查过使用和不使用 PIPE
时调用的 git 版本相同编辑2:
我将@torek 的回答标记为已接受,因为它完美地解决了我的问题。
不过,我应该说明我使用 git-log 的目的是为了获得更广泛的答案。
My goal is to find the tag that is the first tag found when traveling back in history (topological or graph ordering) and that matches a regular expression.
我以前使用过 rev-list,但没有发现任何文档表明这会按我想要的顺序传送标签,也许我错过了什么。
当我同时声明我需要正则表达式匹配时,我在我的命令中使用简单的 glob 模式的原因是我假设 globbing 更快,因此将它用作预过滤器以缩短python中需要正则表达式解析的列表。我希望标签列表在几年内包含 1000 多个标签并且还在增长。其中带有单词 'platVer' 的标签将占该列表的 1% 左右。
将 --decorate=full
或 --decorate=short
添加到您的 git log
参数中。您也可以使用 --decorate=true
或 --decorate=1
,但现在 full
和 short
是记录值。完整包括全名(例如,refs/heads/somebranch
),而 short
缩写为分支或标签名称。
很长(但可选)有用的背景信息
默认的 log.decorate
设置是 auto
(从 Git 2.9 开始;之前是 no
/0
/false
, 并且在不同的地方引入了各种错误,然后在以后的版本中修复;它自 Git 2.13) 以来一直稳定。 auto
设置意味着 short
如果人类正在读取输出,no
如果程序正在读取输出 .1
--simplify-by-decoration --decorate-refs=...
需要装饰本身(即必须打开)才能工作。可能这些选项中的任何一个都应该暗示 --decorate=short
如果它目前仍然 auto
在 Git 配置中未设置。2
这一切都指向以编程方式使用 git log
的更普遍的问题,例如,从 Python 和 subprocess
:git log
是 Git 调用的内容porcelain命令,这意味着它服从用户配置。如果用户有 log.decorate
设置,它将覆盖任何默认值。现在您了解了 log.decorate
和 --decorate=
参数,您可以使用 --decorate=
参数(它会覆盖任何用户配置)在程序中强制执行正确的行为。但是 other 用户可配置的项目存在于 git log
中会破坏你的程序吗? Git 的未来版本,其中 git log
可能会获取新的配置项?不幸的是,今天 你 对这个更普遍的问题无能为力,但由于 git log
所做的某些事情不能由任何所谓的 [=83] =]plumbing 命令——这些命令 不会 根据用户配置更改行为,因此对于其他程序很有用,因为它们具有已知的固定输出格式—git log
需要一个选项来让它表现良好。 (git status
命令对此有 --porcelain
选项;git log
只需要它自己的版本。)
1Git 实际上 不知道 是否有人正在阅读输出。相反,它通过检查标准输出流来近似:如果标准输出(文件描述符 1)响应 isatty
C 库调用的真值,或者 git log
输出被馈送到寻呼机,它假设一个人正在阅读输出。在 subprocess
中使用管道意味着 stdout 是 而不是 tty,默认情况下它也会禁用寻呼机。但是,有一个强制使用寻呼机的用户配置设置:请参阅“更一般的问题”段落。
2一般来说,Git配置的工作方式是这样的:
首先,程序设置任何自动默认值,例如
log.decorate=auto
(这通常只是开放编码,而不是使用配置机制)。接下来,Git读取系统配置文件。如果其中有
log.decorate=short
之类的设置,则应用该设置,覆盖自动默认值。 (这通常通过回调,从配置机制到程序。)接下来,Git读取您的个人全局配置文件。如果其中有
log.decorate=auto
等设置,则应用该设置。如果之前的配置有设置,这将覆盖之前的设置。接下来,Git 读取此特定 Git 存储库的配置文件。如果它有诸如
log.decorate=full
之类的设置,则应用该设置,并像以前一样覆盖任何以前的设置。最后,Git 应用命令行参数设置。因此,这些会覆盖在前面任何步骤中选择的任何设置。
例如,您可以这样安排 user.name
and/or user.email
对于一个特定的 Git 存储库来说是不同的。您在全局配置中设置这些,Git 在读取每个存储库配置之前读取;然后在每个存储库配置中将它们设置为不同的值,并覆盖全局配置。
在 Git 的较新版本中,您还可以设置 每个工作树配置: git config --worktree
。这是在每个存储库配置文件之后读取的,但在命令行参数之前使用,因此它具有第二高的优先级。要使每个工作树设置生效,您必须启用 extensions.worktreeConfig
。在这里要小心,因为这个扩展有一段时间存在一些错误。