bash 阻止将琐碎合并推送到 git 服务器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4138285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
block push of trivial merge to git server
提问by Adam Monsen
A while back I asked our developers to use rebase instead of merge before pushing. Eliminating trivial merges makes for a much easier to follow commit graph (ie: gitk, git log).
不久前,我要求我们的开发人员在 push 之前使用 rebase 而不是 merge。消除琐碎的合并使得更容易跟踪提交图(即:gitk、git log)。
Sometimes folks still accidentally do trivial merges, then push. Does anyone have handy or have tips for writing a server-side hook that blocks trivial merges?
有时人们仍然会不小心进行琐碎的合并,然后推送。有没有人有编写阻止琐碎合并的服务器端挂钩的方便或技巧?
By "trivial merge", I mean a merge without conflicts. Here's an example, and here's a better explanation of a trivial merge in git.
通过“平凡的合并”,我的意思是没有冲突的合并。这是一个示例,这是对 git 中的琐碎合并的更好解释。
Update Wed Nov 10 01:26:41 UTC 2010: great comments, all! Thank you.
UTC 2010 年 11 月 10 日星期三 01:26:41 更新:所有评论都很棒!谢谢你。
- Consider the following: all I'm really asking folks to do is this:
- if
git pull --ff-onlyfails, dogit pull --rebaseinstead ofgit pull
- if
- git.git only has one or two committers, right? In theory, it should be easy to follow the commit graph, but it looks pretty messy to me.
- 考虑以下几点:我真正要求人们做的就是:
- 如果
git pull --ff-only失败,请执行git pull --rebase而不是git pull
- 如果
- git.git 只有一两个提交者,对吗?从理论上讲,遵循提交图应该很容易,但对我来说它看起来很混乱。
Update Thu Nov 11 23:49:35 UTC 2010:
UTC 2010 年 11 月 11 日星期四 23:49:35 更新:
- here's a gist with some in-progress work
- another idea is to prevent trivial merges on the client end, with a "git push" wrapper
- 这是一些正在进行的工作的要点
- 另一个想法是防止在客户端进行琐碎的合并,使用“git push”包装器
Update Wed Dec 15 18:34:52 UTC 2010:
UTC 2010 年 12 月 15 日星期三 18:34:52 更新:
- adymitrukis close! Just one case is still unresolved: non-trivial merges must still work.
- A rather complete test suiteis available, check it out.
- I asked for help on a (the?) git mailing list.
- adymitruk就在附近!只有一种情况仍未解决:非平凡的合并必须仍然有效。
- 有一个相当完整的测试套件可用,请查看。
- 我在 (the?) git mailing list上寻求帮助。
采纳答案by Olivier Refalo
I came across this piece of code, while trying to find a solution. It doesn't do exactly what you want, but it should be ez to add extra branch names on the if statement.
我在试图找到解决方案时遇到了这段代码。它并不完全符合您的要求,但应该在 if 语句中添加额外的分支名称。
Works for me, so far. it forces pull --rebase for the same branch and lets regular merges with other branches go through.
到目前为止,对我有用。它强制 pull --rebase 用于同一分支,并让与其他分支的常规合并通过。
All credits go to the original author.
所有学分归原作者所有。
#!/bin/bash
#
# This git update hook will refuse unnecessary merge commits caused by pulling
# from being pushed to a shared repository. These commits make following the
# history of a project difficult and are always avoidable with rebasing.
#
# by Scott Kyle (appden)
# modified by Olivier Refalo (orefalo)
refname=""
oldrev=""
newrev=""
# if this is not run as a hook, you may have messed up
if [ -z "$GIT_DIR" -o -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: GIT_DIR=<path> #!/bin/bash
refname=""
oldrev=""
newrev=""
branches="refs/heads/hotfixes refs/heads/dev refs/heads/qa refs/heads/master"
cont="no"
for branch in $branches ; do
if [[ $refname == $branch ]] ; then
cont="yes"
fi
done
if [[ $cont == "no" ]] ; then
exit 0
fi
echo "inspecting branch $refname for trivial merges" >&2
hashes="$(git log --format=%H --merges $oldrev..$newrev)"
for hash in $hashes ; do
echo "checking merge commit $hash" >&2
cont="no"
for branch in $branches ; do
if [[ $refname == $branch ]] ; then
continue
fi
# if [[ "$(git log --format=%H $hash^2 ^$branch | wc -l)" == "0" ]] ; then
if [[ "$(git log --format=%H $hash^2 ^$branch | wc -l)" == " 0" ]] ; then
cont="yes"
fi
done
if [[ $cont == "no" ]] ; then
echo "No trivial merges allowed. Please rebase and push again." >&2
exit 1
fi
done
exit 0
<ref> <oldrev> <newrev>" >&2
exit 1
fi
# if the new revision is all 0's then it's a commit to delete a ref
zero="0000000000000000000000000000000000000000"
# also check if the new revision is not a commit or is not a fast forward
# detect branch deletion, branch creation... and more
if [ "${refname#refs/heads/}" = "master" ] || [ "$newrev" = "$zero" ] || [ "$oldrev" = "$zero" ] || [ $(git cat-file -t $newrev) != "co
mmit" ] || [ $(git merge-base $oldrev $newrev) != "$oldrev" ]; then
exit 0
fi
# loop through merges in the push only following first parents
for merge in $(git rev-list --first-parent --merges $oldrev..$newrev --); do
# lazily create the revision list of this branch prior to the push
[ -z "$revlist" ] && revlist=$(git rev-list $oldrev)
# check if the second parent of the merge is already in this branch
if grep -q $(git rev-parse $merge^2) <<< "$revlist"; then
cat >&2 <<-EOF
*** PUSH REJECTED ***
*** TRIVIAL merge detected on local branch ${refname#refs/heads/}
*** To fix: git rebase origin/${refname#refs/heads/}
***
*** Next time use: git pull --rebase
***
*** Permanent fix: git config [--global] branch.autosetuprebase always
*** Then for existing branches: git config branch.<name>.rebase true
EOF
exit 1
fi
done
echo -Info- Clean history successfully preserved!
exit 0
回答by Adam Dymitruk
This update hookwill check if you are pushing to specific branches (it allows trivial merges in wip, topic and other branches).
此更新挂钩将检查您是否正在推送到特定分支(它允许在 wip、主题和其他分支中进行微不足道的合并)。
This does not bother with the rest of the parents on octopus merges as it only references the 2nd parent in each merge commit being pushed. Please feel free to update the script.
这不会影响章鱼合并的其余父级,因为它只引用每个被推送的合并提交中的第二个父级。请随时更新脚本。
UPDATE: Reserved branches are required to exist on the remote.
更新:保留分支需要存在于远程。
##代码##
