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

Git提交策略,将对特定文件的更改隔离为单独的提交,git,Git,我想要求SVG独立于其他内容,以保持其他内容的差异输出更干净。例如,我想禁止这样的提交: $ 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:

我想要求SVG独立于其他内容,以保持其他内容的差异输出更干净。例如,我想禁止这样的提交:

$ 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状态
论分行行长
要提交的更改:
(使用“git重置磁头…”取消分级)
新文件:src/css/main.css
修改:src/images/example.svg
修改:src/index.html
这可以通过预提交钩子实现吗?那怎么写呢

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

这可以通过预提交钩子实现吗

对。(但请注意,此类挂钩可以绕过。)

那怎么写呢

这取决于你想用什么语言来写

Shell脚本往往是最简单的,因为您可以直接运行Git工具。在这里,您可以运行
git diff index--name status
,将索引(建议的提交)与当前(即
HEAD
commit)进行比较,然后通读正在添加、修改或删除的文件,查看是否有以
.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
#直接来自示例预提交挂钩
如果git rev parse--验证HEAD>/dev/null 2>&1
然后
顶头
其他的
#初始提交:针对空树对象的差异
反对=4B825DC642CB6EB9A060E54BF8D6928FBEE4904
fi
#创建一个临时文件以保存差异输出
tmpfile=$(mktemp)
陷阱“rm-f$tmpfile;退出”01 2 3 15
git diff index--cached--name only--diff filter=ADM$对>$tmpfile
#从临时文件中读取状态和名称。
#我们使用临时文件只是因为“读取时…”运行
#一个子外壳,意味着变量更改不会导致
#它将返回到父shell。还有其他解决办法
#但这个很简单。
num_svg=0
num_nonsvg=0
读名字时;做
中的大小写“$name”
*.svg)num_svg=$((num_svg+1));;
*)num_nonsvg=$((num_nonsvg+1));;
以撒
完成<$tmpfile
#现在,如果存在混合的svg和非svg文件,则不允许提交
如果[$num_svg-gt 0-a$num_nonsvg-gt 0];然后
echo“此提交同时影响.svg文件和非svg文件”1>&2
出口1
fi
#这里还有其他检查吗
出口0

(注意:这完全没有经过测试)

如果上面的脚本有svg文件,它将阻止提交。但是,我们是否可以在不单独使用svg文件的情况下允许提交,并将svg文件添加到钩子脚本本身的新提交中?注意:这可能不是OP所要求的。但我正在寻找一些解决方案,比如that@karthick:理论上可以让钩子单独提交,但这不是个好主意。不要这样做:而是编写一个脚本来进行提交。脚本可以禁用任何挂钩(使用
--no verify
)或设置控制挂钩的环境变量(使用您喜欢的任何代码)。是否
git ls files-dmo--exclude standard
会产生与
git diff index
命令相同的结果?否,
git ls files
读取索引(“将提交什么”),并且可以选择性地将其与当前工作树进行比较(这是
-d
-m
所做的),但根本不将其与
提交进行比较。使用
git diff index--cached
HEAD
(“现在提交的内容”)与索引进行比较。请注意,它完全未经测试,因为我尝试时它不起作用。我在最后一个测试中添加了一个
else
,该测试将打印计数器变量以查看发生了什么:
echo“DEBUG:num\u svg:$num\u svg num\u nonsvg:$num\u nonsvg”1>&2
输出总是
DEBUG:num\u svg:0 num\u nonsvg:0
请不要将已解决的问题附加到标题。取而代之的是把答案标记为“接受”。这将告诉其他人问题现在已经解决了。谢谢。更新:我的问题是一个实例,因为我的最终目标是“保持其他所有内容的差异输出更干净”。我最终被说服,将对
.svg
文件的更改分离到它们自己的提交中会违反提交的原则。我现在使用的是一个
.gittributes
文件,其中有一行
*.svg-diff
。这告诉Git将
.svg
文件视为二进制文件,因此它将输出“二进制文件不同”作为diff消息。