Git提交策略将对特定文件的更改隔离为单独的提交

时间:2017-08-07 23:11:24

标签: git

我想要要求SVG与其他所有内容分开提交,以保持其他所有内容的diff输出更清晰。例如,我想禁止像这样的提交:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   src/css/main.css
        modified:   src/images/example.svg
        modified:   src/index.html

这可以通过预提交挂钩完成吗?怎么会写?

编辑:我认为git ls-files -dmo在这里很有用,但我不知道如何编写脚本来解析其输出。

1 个答案:

答案 0 :(得分:2)

  

这可以通过预提交钩子完成吗?

是。 (但请注意,可以绕过这种钩子。)

  

怎么写?

取决于您要用什么语言来编写它。

Shell脚本往往是最简单的,因为您可以直接运行Git工具。在这里,您可以运行git diff-index --name-status来比较索引(建议的提交)与当前的ie HEAD提交,然后读取正在添加,修改或删除的文件以查看是否有任何名称以.svg,如果有任何名称以其他任何结尾。这使您可以调整规则以允许删除 .svg文件,同时进行其他更改。或者,如果文件状态(添加/删除/修改)不相关,则更简单一点:

# straight from the sample pre-commit hook
if git rev-parse --verify HEAD >/dev/null 2>&1
then
        against=HEAD
else
        # Initial commit: diff against an empty tree object
        against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# create a temp file to hold diff output
tmpfile=$(mktemp)
trap "rm -f $tmpfile; exit" 0 1 2 3 15
git diff-index --cached --name-only --diff-filter=ADM $against > $tmpfile

# read the status and names from the temp file.
# we use a temp file simply because "| while read ..." runs
# a sub-shell which means that variable changes don't make
# it back to the parent shell.  there are other workarounds
# but this one is simple.
num_svg=0
num_nonsvg=0
while read name; do
    case "$name" in
    *.svg) num_svg=$((num_svg + 1));;
    *) num_nonsvg=$((num_nonsvg + 1));;
    esac
done < $tmpfile

# now disallow commit if there are mixed svg and non-svg files
if [ $num_svg -gt 0 -a $num_nonsvg -gt 0 ]; then
    echo "this commit affects both .svg files and non-svg files" 1>&2
    exit 1
fi
# run any other checks here too
exit 0

(注意:这是完全未经测试的)