检查暂存文件是否再次被修改的预提交挂钩
pre-commit hook that checks if staged files were modified again
我正在尝试编写一个 git 预提交挂钩,用于检查使用 git add
暂存的文件在提交之前是否再次被修改。
基本上我对这些文件感兴趣
git status --short
MM test1
AM test2
现在预提交挂钩如下所示:
#!/bin/bash
# git pre-commit hook that checks for staged files that were modified.
# exit on error
set -e
# DOES NOT WORK
cached=$(git diff --name-only --diff-filter=M)
# everything is fine
if ! [[ -n $cached ]]; then
exit 0
fi
# GNU and BSD versions of xargs behave differently.
if xargs --version >/dev/null 2>&1; then
flag="-l" # GNU
else
flag="-L1" # BSD
fi
printf "The following files have been modified after they have been staged:\n\n"
printf "$cached"
printf "\n\nYou can stage these changes with:\n"
printf " git diff --name-only --cached | xargs ${flag} git add\n"
printf "Aborting commit. Stage the modified files and commit again or skip"
printf " checking with --no-verify (not recommended).\n"
exit 1
问题是,此挂钩还会拾取已修改但未暂存的文件。我该如何调整我的鱼钩?
要使用 git diff
执行此操作,您需要两遍,一次查找在索引中添加或修改的文件(git diff --cached --name-status
或类似文件),另一遍查找自索引版本以来修改的文件 ( git diff --name-status
或类似的)。
但您不必使用 git diff
执行此操作。答案就在你的短语中:
Basically I am interested in these files ...
只需 运行 git status --short
(或 --porcelain
)和 grep for ^[AM]M
:这些是您的文件。 运行 通过某些东西切掉状态部分(cut
、sed
等)的输出;这些是名字。
sed
命令可以进行匹配和切割,并且比awk
更轻量,所以可能是最好的工具:
git status --porcelain | sed -n 's/^[AM]M //p'
存在一个缺陷:对于 git status
检测到重命名或复制操作的文件(最左侧列中的 R
和 C
),您可能会遗漏一些索引 - vs-work-tree 变化。在工作树中还有 D
eleted-in-commit 但 M
odified(未删除)。我不确定你是否关心这些案例。如果是这样,请通读 the git status
documentation 中的详细信息并相应地修改 sed 正则表达式。
(有一个单独的缺陷:如果您正在进行合并,git status
会告诉您有关合并的信息。但是,在完成合并之前您不能提交,所以我只提到这一点,以防有人想在预提交挂钩以外的其他地方使用同样的想法。)
我正在尝试编写一个 git 预提交挂钩,用于检查使用 git add
暂存的文件在提交之前是否再次被修改。
基本上我对这些文件感兴趣
git status --short
MM test1
AM test2
现在预提交挂钩如下所示:
#!/bin/bash
# git pre-commit hook that checks for staged files that were modified.
# exit on error
set -e
# DOES NOT WORK
cached=$(git diff --name-only --diff-filter=M)
# everything is fine
if ! [[ -n $cached ]]; then
exit 0
fi
# GNU and BSD versions of xargs behave differently.
if xargs --version >/dev/null 2>&1; then
flag="-l" # GNU
else
flag="-L1" # BSD
fi
printf "The following files have been modified after they have been staged:\n\n"
printf "$cached"
printf "\n\nYou can stage these changes with:\n"
printf " git diff --name-only --cached | xargs ${flag} git add\n"
printf "Aborting commit. Stage the modified files and commit again or skip"
printf " checking with --no-verify (not recommended).\n"
exit 1
问题是,此挂钩还会拾取已修改但未暂存的文件。我该如何调整我的鱼钩?
要使用 git diff
执行此操作,您需要两遍,一次查找在索引中添加或修改的文件(git diff --cached --name-status
或类似文件),另一遍查找自索引版本以来修改的文件 ( git diff --name-status
或类似的)。
但您不必使用 git diff
执行此操作。答案就在你的短语中:
Basically I am interested in these files ...
只需 运行 git status --short
(或 --porcelain
)和 grep for ^[AM]M
:这些是您的文件。 运行 通过某些东西切掉状态部分(cut
、sed
等)的输出;这些是名字。
sed
命令可以进行匹配和切割,并且比awk
更轻量,所以可能是最好的工具:
git status --porcelain | sed -n 's/^[AM]M //p'
存在一个缺陷:对于 git status
检测到重命名或复制操作的文件(最左侧列中的 R
和 C
),您可能会遗漏一些索引 - vs-work-tree 变化。在工作树中还有 D
eleted-in-commit 但 M
odified(未删除)。我不确定你是否关心这些案例。如果是这样,请通读 the git status
documentation 中的详细信息并相应地修改 sed 正则表达式。
(有一个单独的缺陷:如果您正在进行合并,git status
会告诉您有关合并的信息。但是,在完成合并之前您不能提交,所以我只提到这一点,以防有人想在预提交挂钩以外的其他地方使用同样的想法。)