git 尝试创建一个预提交挂钩,检查索引中的文件格式是否正确

e5nszbig  于 2023-02-14  发布在  Git
关注(0)|答案(1)|浏览(117)

我一直在尝试做一个pre-commit钩子来检查索引中的文件格式是否正确。我已经尝试了很多方法,但就是不能让grep正常工作。下面是我现在的代码:

for FILE in $(git diff --cached --name-only)
do
    if [[ "$FILE" =~ \.(c|h|cpp|cc)$ ]]; then
        exec C:/dev/uct/clang-format-15.0.3.exe --dry-run -Werror $FILE | grep -c "violations"
    fi
done

我希望它能打印出有格式问题的文件的数量(我实际上想搜索string -Wclang-format-violations,但我为了测试而简化了它)。
如果我&〉clang格式输出到一个文件中,那么违规就正确地打印到该文件中。

exec C:/dev/uct/clang-format-15.0.3.exe --dry-run -Werror $FILE &> temp.txt

如果我从命令行对该文件运行grep,它就会工作。

grep -c violations temp.txt

我还尝试从脚本对文件执行grep,但由于某种原因,也没有产生任何输出(尽管我更希望不必创建文件)。

exec C:/dev/uct/clang-format-15.0.3.exe --dry-run -Werror $FILE &> temp.txt
grep -c violations temp.txt

我做错了什么?我以为我最多半个小时就能让这个工作。

bvjxkvbb

bvjxkvbb1#

grep的问题在于,您没有重定向stderr,而只是重定向stdout(在重定向到文件时,您也使用>&重定向stderr)。要在管道中捕获stderr,请使用|&

  • 然而,* 提交的文件和你看到的文件不匹配。在git中,* file * 不是提交的文件,但它的内容是提交的文件。这意味着你可以提交文件的一部分内容。因此,工作目录中的文件内容与提交的文件内容不匹配。

下面是一个具体的例子:

echo "hello" > hello_world.txt
git add hello_world.txt
echo "world" >> hello_world.txt

此时,索引中暂存的内容(来自第2行的git add)是hello,但文件在磁盘上包含hello world
git status将文件同时显示为已暂存 * 和 * 已修改:

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   hello_world.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   hello_world.txt

如果您现在运行git commit,则只会提交hello,而不会提交磁盘上存在的文件。
这意味着您希望查看文件的 * 暂存内容 *--这是实际提交的内容--而不仅仅是磁盘上的文件,否则您可能会得到误报或漏报。
要处理这种情况,可以使用git show命令将暂存的内容传递给clang-formatgit show :filename将输出filename的 * staged * 内容)。
试试这个:

for FILE in $(git diff --cached --name-only)
do
    if [[ "$FILE" =~ \.(c|h|cpp|cc)$ ]]; then
        git show ":${FILE}" | C:/dev/uct/clang-format-15.0.3.exe --dry-run -Werror --assume=filename="${FILE}" |& grep -c "violations"
    fi
done

相关问题