我正在使用类似于this one的方法来使用预提交挂钩来跟踪对数据库模式的更改(以及一些元数据表)。
我喜欢尝试保持我的提交干净,所以我希望在提交/提交自动更改时在提交消息中大声警告。以下是我的pre-commit
和pre-commit-msg
挂钩:
的.git /钩/预提交
#!/bin/sh
# Save user changes to db/ (if any)
git diff --quiet db/
user_dirty=$?
[[ $user_dirty > 0 ]] && git stash save --keep-index
# Regenerate db/ automatically
db/save_schema_and_meta_tables.sh
# Were any automatic changes made? If so, commit them but warn about it
git diff --quiet db/
auto_dirty=$?
if [[ $auto_dirty > 0 ]]; then
git add db/
echo "WARNING: automatic changes to db/ added to commit" | tee .git/COMMIT_WARNING
fi
[[ $user_dirty > 0 ]] && git stash pop
exit 0
的.git /钩/准备提交-MSG
#!/bin/sh
msgf=$1
wf=.git/COMMIT_WARNING
if [ -e $wf ]; then
msg=$(<$msgf)
( cat $wf; echo "$msg" ) > $msgf
rm -f $wf
fi
以下是它的表现:
db/
进行了更改但尚未暂存,则可以将它们保存在工作树中而不会干扰提交,这要感谢stash save --keep-index
和stash pop
。好!db/
进行暂存更改并且它们被自动提交覆盖,那么用户意图的更改将在提交后消失。糟糕!以下是我喜欢发生的事情:如果db/
存在用户阶段的更改,并且它们与自动更改不完全匹配,则整个事情应该中止。我在弄清楚如何实现这个问题时遇到了很多麻烦:如何保存用户所做的分阶段更改,然后查看自动更改是否不匹配?
答案 0 :(得分:1)
它不漂亮,而且速度很慢,但是根据@ torek的一些建议,我提出了以下建议。
db/
目录(如果是user_staged=1
)db/
目录db/
目录的暂存版本与自动生成的版本(auto_changes=1
进行比较,如果它们不同)db/
db/
匹配,一切正常 db/
不匹配,中止 db/
进行任何更改,但有自动生成的更改,请暂停并继续,但警告在提交消息中 pre-commit
挂钩代码:
# Has user staged changes to db/?
git diff --quiet --staged db/
user_staged=$?
# Stash any user changes in the working tree
old_stash=$(git rev-parse -q --verify refs/stash)
git stash save -q --keep-index
new_stash=$(git rev-parse -q --verify refs/stash)
[[ "$old_stash" != "$new_stash" ]] && stashed=1 || stashed=0
# Automatically regenerate db/
db/save_schema_and_meta_tables.sh
cp -a db db_AUTO
# Compare automatically-generated changes to what the user had already staged
git diff --quiet db/
auto_changes=$?
# Restore user's state
[[ $stashed ]] && git reset --hard -q && git stash apply --index -q && git stash drop -q
# abort: if user had staged changes to db/, and automatic changes would overwrite them
# add but warn: automatic changes added, but no user changes to db/
# silent: no user-staged changes, no automatic changes
if (( $auto_changes > 0 )); then
if (( $user_staged > 0 )); then
echo "ERROR: automatic changes to db/ conflict with staged changes"
rm -rf db_AUTO
exit 1
else
rm -rf db/
mv db_AUTO db
git add db/
echo "WARNING: automatic changes to db/ added to commit" | tee .git/COMMIT_WARNING
exit 0
fi
else
rm -rf db_AUTO
fi