python - 从 python 子进程调用 git-log 时忽略选项 --decorate-refs
问题描述
我被这个错误困住了。我试图搜索一堆东西,我尝试使用调试器跟踪调用。我一点也不聪明。
我的问题:
我从命令行运行这个命令
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*'
并仅列出整个参考集
>>> 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 的目标,以便获得更广泛的答案。
我的目标是找到返回历史时找到的第一个标签(拓扑或图形排序)并且匹配正则表达式的标签。
我之前使用的是 rev-list,但没有发现文档表明这会按照我想要的顺序传递标签,也许我错过了一些东西。
当我同时声明我需要正则表达式匹配时,我在命令中使用简单的 glob 模式的原因是我假设 glob 更快,因此将其用作预过滤器来缩短需要的列表由python中的正则表达式解析。我希望标签列表在几年内包含 1000 多个标签并且还在不断增长。其中带有单词“platVer”的标签将占该列表的 1% 左右。
解决方案
添加--decorate=full
或添加--decorate=short
到您的git log
论点。您也可以使用--decorate=true
or --decorate=1
,但full
andshort
是这些天记录的值。Full 包括全名(例如,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 所谓的瓷器命令,这意味着它服从用户配置。如果用户有一个log.decorate
设置,它会覆盖任何默认值。现在您已经了解log.decorate
了--decorate=
参数,您可以使用--decorate=
参数(它覆盖任何用户配置)在程序中强制执行正确的行为。但是还有哪些其他用户可配置的项目git log
可能会破坏您的程序?未来版本的 Git怎么样,哪里git log
可以获得新的配置项?你什么都没有git log
不幸的是,今天可以解决这个更普遍的问题,但是由于任何所谓的管道命令都无法完成某些事情- 这些命令不会根据用户配置改变行为,因此从其他程序,因为它们具有已知的、固定的输出格式——<code>git log 需要一个选项来使其表现良好。(该git status
命令有这个--porcelain
选项;git log
只需要它自己的版本。)
1 Git 实际上并不知道是否有人在读取输出。相反,它通过检查标准输出流来近似这一点:如果标准输出(文件描述符 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 应用命令行参数设置。因此,这些会覆盖在前面的任何步骤中选择的任何设置。
例如,这就是您可以为一个特定的 Git 存储库安排您的user.name
和/或不同的方式。user.email
您在全局配置中设置这些,Git 在读取每个存储库配置之前会读取这些配置;然后在每个存储库配置中将它们设置为不同的值,这会覆盖全局配置。
在相对较新的 Git 版本中,您还可以设置每个工作树的配置: git config --worktree
. 这是在每个存储库配置文件之后读取的,但在命令行参数之前使用,因此它具有第二高的优先级。要使 per-worktree 设置生效,您必须启用extensions.worktreeConfig
. 在这里要小心,因为这个扩展有一段时间存在一些错误。
推荐阅读
- javascript - 我设置边距的功能无法始终如一地工作
- python - 立即处理异步响应
- python - 将 Flask 与 SQLAlchemy 和 Dash 一起使用
- maven - 在远程服务器上部署之前如何更改一些 java 变量?
- java - 如何在其中一个模块中构建没有主类的多模块 Maven 项目
- javascript - TypeScript 有 NaN 类型吗?
- android - MVVM RXAndroid 无法在后台线程上调用 setValue
- mysql - 在 Sequelize 中返回具有更新关联的对象
- java - 我的方法是 ENUM 类,我不适用于参数(字符串)
- javascript - 如何将纹理图像映射到着色器几何体上?