让git显示它正在运行内容过滤器的特定文件名

让git显示它正在运行内容过滤器的特定文件名,git,debugging,git-filter,Git,Debugging,Git Filter,我正在调试一个配置好的git内容过滤器(nbstripout)的工作,我试图让git_TRACE显示它正在运行的文件,但它没有。考虑: $ GIT_TRACE=1 git pull origin master [...] removed irrelevant sections of the output 16:49:28.846707 run-command.c:640 trace: run_command: git merge FETCH_HEAD 16:49:28.849309

我正在调试一个配置好的git内容过滤器(
nbstripout
)的工作,我试图让
git_TRACE
显示它正在运行的文件,但它没有。考虑:

$ GIT_TRACE=1 git pull origin master
[...] removed irrelevant sections of the output
16:49:28.846707 run-command.c:640       trace: run_command: git merge FETCH_HEAD
16:49:28.849309 git.c:344               trace: built-in: git merge FETCH_HEAD
Updating 1ea49ad..ae0ba93
16:49:28.863291 run-command.c:640       trace: run_command: nbstripout
16:49:28.864700 run-command.c:640       trace: run_command: nbstripout
16:49:28.866060 run-command.c:640       trace: run_command: nbstripout
[...] many more of the same
如何获取GIT_TRACE的
run_命令
,以显示传递给过滤器的参数?我在git的手册中查看了各种其他调试环境变量,但没有看到任何能够启用该级别调试的内容

我知道git check attr,但我希望看到它在哪些文件上运行过滤器以及使用哪些参数的运行时跟踪


git版本2.17.1

我在git邮件列表和Jeff King上发布了这个问题。经杰夫允许,我在这里分享他的答案:


GIT_跟踪应始终显示参数。但除非你具体说明 在clean/smudge过滤器配置中使用参数,那么Git将不会传递任何参数。 stdin/stdout流才是最重要的

例如:

  $ echo '* filter=foo' >.gitattributes
  $ git config filter.foo.clean 'myfilter'
  $ GIT_TRACE=1 git add .
  19:42:16.516401 [pid=14112] git.c:415             trace: built-in: git add .
  19:42:16.517454 [pid=14112] run-command.c:637     trace: run_command: myfilter

  $ git config filter.foo.clean 'myfilter --foo'
  $ touch .gitattributes ;# make sure we actually read it again ;)
  $ GIT_TRACE=1 git add .
  19:42:58.122942 [pid=14156] git.c:415             trace: built-in: git add .
  19:42:58.124023 [pid=14156] run-command.c:637     trace: run_command: 'myfilter \
--foo'
您可以使用“%f”传递文件名,如:

  $ git config filter.foo.clean 'myfilter %f'
  $ touch .gitattributes
  $ GIT_TRACE=1 git add .
  19:44:51.187177 [pid=14318] git.c:415             trace: built-in: git add .
  19:44:51.188256 [pid=14318] run-command.c:637     trace: run_command: 'myfilter \
'\''.gitattributes'\'''
当然,如果您的过滤器实际上尊重 论点对于“干净”的过滤器,这可能是正常的(例如,如果它只是告诉 您的筛选器需要从文件系统而不是stdin中读取),但是 几乎肯定不是你想要的“污迹”过滤器

您可以使用一些shell黑客来解决此问题:

  git config filter.foo.clean 'f() { echo >&2 "cleaning $1"; myfilter ...; }; f %f'
即使没有GIT_跟踪,您也会得到:

  $ git add .
  cleaning .gitattributes
或者,如果您真的只想触发GIT_跟踪,请尝试以下方法:

  $ git config filter.foo.clean 'f() { myfilter; }; f %f'
  19:52:52.874064 [pid=14719] git.c:415             trace: built-in: git add .
  19:52:52.875115 [pid=14719] run-command.c:637     trace: run_command: 'f() { \
myfilter; }; f '\''.gitattributes'\'''
在这里,您可以在跟踪输出中获得名称,但是调用的命令 实际上对它没有任何作用


所以我最终使用了:

[filter "nbstripout"]
    clean  = "f() { echo >&2 \"clean: nbstripout $1\"; nbstripout; }; f %f"
    smudge = "f() { echo >&2 \"smudge: cat $1\"; cat; }; f %f"
    required = true
现在,我在使用GIT_TRACE=1运行时记录了文件名,而不使用它



Jeff在一份声明中建议,有一天git可能会直接支持这一点,而不需要解决方法

建议它应该已经在这里打印argv了。看看源代码@torek真是个好主意!我查看了哪些调用
strbuf_grow()
,哪些(缺少argv跟踪的)没有调用它-也许它应该有那个调用,而argv不知怎么就消失了?这些是非常基本的内部函数,它们必须工作。我的猜测是没有任何争论。过滤函数读取标准输入,写入标准输出;论据,如果有的话,只是提供信息。请注意,现代的“流程式”过滤器(例如Git LFS)使用流式协议来保持一个长时间运行的过滤器尽可能长,通过编码的输入流为其提供“文件”。旧样式的过滤器对每个文件运行一次,但通常不获取参数。这可能解释了跟踪中缺少
argv
。这当然不利于调试。“谢谢你带我找到消息来源并给出合理的解释,@torek。