当 运行 by git 与手动 运行 时相比,使用 echo -n 预提交挂钩的行为不同

Pre-commit hook with echo -n behaving differently when run by git compared to when run manually

我已经编写了一个预提交挂钩来检查我是否不小心使用了制表符来缩进我的新代码。

我通过进行各种更改和 运行 通过键入 $ bash .git/hooks/pre-commit 手动挂钩来模拟由 git 触发的挂钩来开发它(我认为这是一个非常准确的环境).但是,当它实际上是 运行 by git 在提交期间它的行为有所不同。为什么是这样?

这是 bash 脚本的简化示例:

#!/bin/sh

# Default to zero which means the changes are good and the commit can go ahead
exitstatus=0

# Grab the lines with the plus symbol and tab characters at the start (eg. New lines, indented wrongly)
tabbedlines=$( git diff --cached -U0 code/ | egrep "^\+\t" )

# Count the lines (** THIS IS THE BIT THAT BEHAVES DIFFERENTLY **)
tabbedlinecount=$( echo -n "$tabbedlines" | grep -c '^' )

if [ $tabbedlinecount -gt 0 ]
then
  exitstatus=1
fi

exit $exitstatus

本质上,以 tabbedlinecount=... 开头的行表现不同。 echo with the -n flag returns 0 when 运行 in the bash environment but 1 when 运行 by git during a commit .我已经通过将其更改为使用 printf 来证明这一点,它的行为始终如一并因此解决了问题,但即使我已经解决了它,我仍然想了解为什么?!

与我的终端使用的 shell 相比,这与 git 使用的 shell 有关吗?我现在有点不知所措。帮我堆栈溢出,你是我唯一的希望。

您的脚本使用 #!/bin/sh。如果 shell 是 dash(或另一个 strictly 符合 POSIX shell,则 echo -n whatever 的输出是

$ echo -n
-n

也就是说,-n 不被识别为禁止尾随换行符的选项。请改用 printf

$ tabbedlinecount=$( printf '%s' "$tabbedlines" | grep -c '^' )