前一阵子asked our developers to use rebase instead of merge before pushing。消除琐碎的合并使得更容易遵循提交图(即:gitk,git log)。
有时人们仍然会意外地进行琐碎的合并,然后推动。有没有人有方便或有写一个阻止琐碎合并的服务器端钩子的技巧?
通过“琐碎的合并”,我的意思是没有冲突的合并。 Here's an example和here's a better explanation of a trivial merge in git。
更新Wed Nov 10 01:26:41 UTC 2010 :很棒的评论,全部!谢谢。
git pull --ff-only
失败,请git pull --rebase
代替git pull
更新时间:11月11日星期四23:49:35 UTC :
更新Wed Dec 15 18:34:52 UTC 2010 :
答案 0 :(得分:8)
在尝试寻找解决方案时,我遇到了这段代码。它并不完全符合您的要求,但应该在if语句中添加额外的分支名称。
到目前为止对我有用。它强制pull --rebase用于同一个分支,并允许与其他分支的常规合并通过。
所有学分归原作者所有。
#!/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="$1"
oldrev="$2"
newrev="$3"
# 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> $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
答案 1 :(得分:4)
此更新挂钩将检查您是否正在推送到特定分支(它允许在wip,主题和其他分支中进行简单的合并)。
这对章鱼合并中的其余父母没有打扰,因为它只引用每个合并提交中的第二个父项被推送。请随时更新脚本。
更新:遥控器上必须存在保留分支。
#!/bin/bash
refname="$1"
oldrev="$2"
newrev="$3"
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