git 预提交脚本

git 预提交脚本

目标是在提交时以非零退出代码退出脚本,package-lock.json而无需提交任何相关更改package.json

#!/bin/bash

# exits with 1 if there were differences and 0 means no differences
file_changed() {
  git diff --quiet --exit-code "$1"
}

# exits with 1 if no lines were selected, 0 if one or more lines selected, > 1 if error
file_staged() {
  git diff --name-only --cached | grep -q "$1"
}

# package-lock.json has changed and
#   package-lock.json in staged files and
#   package.json not in staged files?
if [[ file_changed "package-lock.json" -eq 1 &&
  file_staged "package-lock.json" -eq 0 &&
  file_staged "package.json" -eq 1 ]]
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

我相当确定问题出在我的files_staged职能上。测试时file_staged "package-lock.json" -eq 0,我得到了预期的结果。测试的时候file_staged "package.json" -eq 1总是失败。

package.json简化问题,当不在返回的文件列表中时,我永远无法触发此条件git diff --name-only --cached

if file_staged "package.json" -eq 1; then
  echo "got here."
fi

我哪里错了?


编辑

@Jesse_b 指出我应该$()在函数调用周围使用,以便数字比较运算符不会作为参数发送给函数。下面的例子仍然没有给出想要的结果:

if [[ $(file_staged "package.json") -eq 1 ]]; then
  echo "got here."
fi

答案1

if您的构造中的任何条件都不起作用。由于您没有使用测试命令(test[[[),您只是测试函数的返回状态。

例子:

$ test () { echo 0; }
$ if test -eq 1; then echo yes; fi
0
yes
$ if test -eq 10; then echo yes; fi
0
yes
$ if test -eq 100000000000; then echo yes; fi
0
yes

-eq ...视为该test函数的一个选项,并且该函数返回 0,因此它被视为成功。

您想使用测试命令:

if [[ $(file_changed "package-lock.json") -eq 1 &&
  $(file_staged "package-lock.json") -eq 0 &&
  $(file_staged "package.json") -eq 1 ]]
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

相关内容