我有一个git pre-commit钩子,在提交之前对任何修改过的文件进行一些样式检查。
实现无关紧要,但首先是调用git diff
。这是(repo)/.git/hooks/pre-commit
中的内容。
#!/bin/sh
echo "=== Running script..."
git diff
echo "=== Done running script..."
# Other stuf
# ....
# Always exit with 1 so pre-commit hook always fails.
# Useful for testing
exit 1
当我实际尝试提交某些内容时,pre-commit
挂钩正确触发,但git diff
命令不输出任何内容(肯定有修改过的文件)
> git commit --all -m "foo"
=== Running script...
=== Done running script...
但是,如果我直接/手动运行pre-commit
挂钩脚本, 工作
> ./.git/hooks/pre-commit
=== Running script...
(... outputs git diff ...)
=== Done running script...
git调用钩子与我手动调用它有什么不同?它以相同的方式运行(我的用户名)
我还尝试了this thread的建议,但unset GIT_DIR
,--git-dir=
和work-tree=
没有解决任何问题。
谢谢!
答案 0 :(得分:2)
您需要使用git diff --cached
,因为更改已经暂存。
答案 1 :(得分:2)
作为ishegg said,您需要git diff --cached
,但这不一定是整个故事。
这里有两个陷阱需要警惕。第一个是git diff
的作用:它比较两个树(或类似树的东西)。第二个与索引。
git diff
通常,您区分的两棵树是与两个特定提交相关联的树:
git diff <hash1> <hash2>
(或与<hash1>..<hash2>
相同,与大多数Git命令不同 - 不以两点..
操作描述的方式处理两个哈希the SPECIFYING RANGES section of the gitrevisions documentation)。
将两棵树中的一棵树作为工作树也很常见,这就是你跑步时会发生的事情:
git diff HEAD
例如:将HEAD
命名的提交 - 即当前的分支提示提交 - 与当前工作树进行比较。
使用:
git diff --cached
告诉Git将HEAD
提交与索引所代表的树进行比较。 Git的索引,也称为临时区域或缓存,是Git构建下一个提交的地方。这就是你必须在提交之前运行git add
的原因:git add
命令将文件从工作树复制到索引。
使用:
git diff
没有任何参数选择索引作为第一个树,工作树作为第二个树。一旦所有内容都从工作树复制到索引中,这个特殊的差异将是空的,这就是你在这里看到的。
第二个陷阱在于你正在使用git commit --all
。
虽然Git谈到 索引,并且实际上有一个特定的,区别于每个工作树的索引,Git实际上允许多个索引,一次只使用一个
当您使用git commit --all
或将文件名传递给git commit
时,Git会在预提交过程中创建一个临时索引。为了表明存在临时索引,Git设置了环境变量GIT_INDEX_FILE
。使用此临时索引而不是普通索引,直到允许和提交提交,或直到提交被拒绝为止。
如果提交被拒绝,Git只会删除临时索引,一切都会恢复到之前的状态。如果事情不是git add
,那么它们仍然不是git add
- 编辑。
如果提交已接受,则临时索引或多或少变为“真实”或“主要”索引。这里的事情可能变得复杂,因为您可以在真实索引中运行一些项目,运行git commit --all
或git commit --include <paths>
或git commit --only <paths>
,如果提交成功,则初始(主要或真实的)指数和临时指数很重要。
如果您计划对工作树中的文件和/或索引中的副本执行特殊操作,您可能只想拒绝任何使用临时索引的尝试,以避免这些复杂情况。但是,这将排除使用--all
。