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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:53:39  来源:igfitidea点击:

block push of trivial merge to git server

gitbashgit-branchgithooksgit-merge

提问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, do git pull --rebaseinstead of git pull
  • 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 更新

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.

更新:保留分支需要存在于远程。

##代码##