预先推送Git以防止合并

时间:2019-01-16 10:36:35

标签: bash git

为了避免错误合并,我为git钩子制作了这个bash脚本。

在工作中,我们使用git-extension并预填充分支名称,如果您忘记为分支名称加上refs / for或refs / drafts前缀,那么您的提交将绕过代码审查在远程仓库中合并。

这只会发生在拥有合并权的人身上。但是有时候拥有合并权的人会犯这个错误。

#!/bin/sh

if [[ `grep 'refs/for'` ]]; then 
  echo "push to refs/for/ authorized"
elif [[ `grep 'refs/drafts/'` ]]; then
  echo "push to refs/drafts/ authorized"
else
  echo "PUSH DENIED, MERGE DETECTED, please merge using gerrit 'submit' button only"
  exit 1
fi

如果我按refs/for/v1.1.x,它将得到push to refs/for/ authorized

但是如果我按refs/drafts/v1.1.x,我会得到PUSH DENIED, MERGE DETECTED, please merge using gerrit 'submit' button only

这怎么可能,条件语法完全相同。

谢谢。

1 个答案:

答案 0 :(得分:1)

Anthony Sottile commented一样,您的第一个grep命令读取所有输入,并检查refs/for。您的第二个grep读取其余的输入;自您的第一个读取输入的 all 以来,没有剩下的。因此,第二个从没找到任何东西。

您可以用许多不同的方式来处理。一种是将stdin复制到可以重复读取的临时文件中。另一个方法是构造挂钩,以便您仅读取一次输入,并针对每种情况检查每一行。第二种方法显然更有效,尽管这种“显而易见性”只是一种幻想,具体取决于我在这里不打算讨论的细节。

无论如何,我的写法是:

#! /bin/sh

summary_status=0     # assume all OK initially
while read lref lhash rref rhash; do
    case $rref in
    refs/for/*|refs/draft/*) echo "push to $rref ok";;
    *) echo "push to $rref not ok"; summary_status=1;;
    esac
done
exit $summary_status

此变体不需要bash功能(因此/bin/sh行中的/bin/bash而不是#!);如果将其更改为可更改的名称,请确保更改#!行。它只读取一次输入。它还会验证您没有运行,例如:

git push remote master:refs/for/master develop

您现有的脚本所允许的(因为一个可以,而另一个不能)。