git属性使用filter smudge/clean通过shell脚本处理.cpp文件,但找不到文件名

git属性使用filter smudge/clean通过shell脚本处理.cpp文件,但找不到文件名,git,attributes,format,Git,Attributes,Format,我想在将所有.cpp文件提交到git之前为它们设置代码样式格式 为此,我制作了一个名为codeformat的小脚本,并尝试用$1重播%f #! /bin/bash clang-format -style=file %f | diff %f -** if [ $? -ne 0 ]; then echo "ERROR: codeformat not correct" exit 1 fi 是否设置了git config并使用*.cpp filter=codeformat更新了.gittr

我想在将所有.cpp文件提交到git之前为它们设置代码样式格式

为此,我制作了一个名为codeformat的小脚本,并尝试用$1重播%f

#! /bin/bash
clang-format -style=file %f | diff %f -**
if [ $? -ne 0 ]; then
   echo "ERROR: codeformat not correct"
   exit 1
fi
是否设置了git config并使用*.cpp filter=codeformat更新了.gittributes

git config --global filter.codeformat.clean codeformat
git config --global filter.codeformat.smudge codeformat
看起来脚本正在运行,但未获取文件名。这是为什么?

您将%f指令放在了错误的位置

如搜索%f中所示:

筛选器命令行上的序列%f已替换为筛选器正在处理的文件名。筛选器可能在关键字替换中使用此选项。例如:

[filter "p4"]
        clean = git-p4-filter --clean %f
        smudge = git-p4-filter --smudge %f
因此,要获取文件的路径名,您需要将filter.codeformat.clean设置为codeformat%f

此时还需要修改bash脚本,因为它的参数替换语法实际上是$1。但是,请阅读gitattributes文档的下一段:

请注意%f是正在处理的路径的名称。根据要筛选的版本,磁盘上相应的文件可能不存在,或者可能有不同的内容。因此,smudge和clean命令不应尝试访问磁盘上的文件,而应仅作为标准输入中提供给它们的内容的过滤器

这里的重点是我的,但这告诉你,你不能简单地打开磁盘文件并读取它。必须仅过滤标准输入,提供标准输出

然而,Diff并非如此

编辑以添加工作示例:

$ cat ~/scripts/dotest
#! /bin/sh
echo "dotest run with $# arguments:" >>/tmp/dotest_log
for i do
    printf '%s\n' "$i"
done >>/tmp/dotest_log
cat
$ which dotest
[path edited]/scripts/dotest
$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[filter "testfilter"]
        clean = dotest %f
        smudge = dotest %f
$ cat .gitattributes
*.test  filter=testfilter
$ echo 'bar.test' > bar.test
$ git add bar.test
$ cat /tmp/dotest_log
dotest run with 1 arguments:
bar.test
%f由git解释,应该在gitconfig中。在shell脚本中,使用$1:


这意味着,我永远无法获取文件名?,我尝试使用git配置本身%f,并将脚本更改为使用$1,但它仍然无法获取文件名

cat ~/.gitconfig

 [filter "codeformat"]
         clean = codeformat %f
         smudge = codeformat %f

cat .gitattributes
    #clang code style format
    *.cpp                           filter=codeformat

 cat codeformat
    #! /bin/bash
    clang-format -i -style=file $1 -
    echo "file/path accessed is _____ $1 ____" > log_output 2>&1

git add src/sample.cpp

    cat log_output
    file/path accessed is _____  ____
下面同样的命令如果我在命令行上运行,效果会很好

clang-format -i -style=file src/sample.cpp
使用git add时,它无法获取文件名,因此出现其他错误 错误:从标准输入读取时无法使用-i


注意这次,我删除了diff命令,使用-i直接替换源文件

我也尝试了,没有帮助,请参见下面的更多详细信息。请参见添加的工作示例。我不知道你做了什么不同,但是我的脚本是用文件名调用的,如/tmp中的日志文件所示。这很有帮助,之前我没有运行git-config,我确实运行了git-config-global,但是我必须单独运行git-config而不运行global才能在.git/config中更新它,否则它只能在~/.gitconfig中更新。现在,它正在打印文件名,我现在需要使用我的代码格式命令。我们可以将错误消息写入screen吗?让我们说一下/tmp/dotest_log中的内容,wehn i trigger git add?我有一些echo命令,而不是重定向到日志,它不写日志,它只提供消息错误过滤器…目标是提供一些消息,以便用户可以遵循,此外,退出内部脚本不是退出git操作,我的git添加仍然成功,即使脚本失败,我们能强迫它在git add修复之前也失败吗?过滤器的stderr连接到git的stderr,因此写入stderr可能会也可能不会写入终端。但是,过滤器的退出状态将被忽略,除非它被标记为必需,在这种情况下,如果过滤器退出非零,Git将声明转换失败,因此整个操作Git add或index to worktree checkout也失败。请注意,如果您编写更复杂的流程过滤器,则整个协议将完全不同;请参阅。是的,required=true正在执行,但它也会触发污迹,即使我的配置中没有污迹过滤器。我可以单独申请清洁吗?这意味着,根本不要触发污点。
clang-format -i -style=file src/sample.cpp