ловушка предварительного получения на стороне сервера, которая отказывается от любого нажатия на мастер, который имеет нелинейную историю - PullRequest
4 голосов
/ 30 марта 2011

Я ищу сценарий оболочки (sh, возможно, не bash), который бы отказывался от любого нажатия на master с любой нелинейной историей.

Я пыталсяскрипт из:

Как избежать "Объединить ветку 'master' из ssh: //gdcm.git.sourceforge.net/gitroot/gdcm/gdcm"

, котораяреализован в ruby, но даже не работает на sourceforge сервере.Я попробовал тогда эквивалент bash:

https://fedorahosted.org/fedora-infrastructure/attachment/ticket/1342/pre-receive

, этот работает, но не делает то, что должен делать (он ничего не отклоняет).

Спасибо за предложения.

Ответы [ 3 ]

3 голосов
/ 31 марта 2011

Вы можете сделать это намного, намного проще, чем ваш хук.

merge_commit=$(git rev-list -n 1 --merges $rev_old..$rev_new)
if [ -n "$merge_commit" ]; then
     echo "Merge commit detected: $merge_commit";
     exit 1
fi

Вы также можете захотеть сделать это хуком обновления, а не хуком предварительного получения. Хук предварительного получения запускается один раз для всего push, принимая входные данные в stdin, в то время как хук обновления запускается один раз для ref, обновляемого, принимая входные данные в качестве аргументов. Это дает вам лучшую гранулярность.

#!/bin/sh
ref=$1
rev_old=$2
rev_new=$3
if [ "$ref" = refs/heads/master ]; then
    ...
fi

Обычно нет необходимости проверять быстрые форварды. Git уже по умолчанию запрещает нажатия без ускоренной перемотки вперед, и если вы хотите запретить их даже при принудительном нажатии, просто установите receive.denyNonFastForwards в значение true в конфигурации. Я предполагаю, что вы хотите отрицать их даже для принудительных толчков, но позволите им в другом месте? Это своего рода контроль доступа, который на самом деле очень хорошо реализован такими вещами, как gitolite, если вы делаете свой собственный хостинг, но я думаю, если это ваше требование, и у вас нет gitolite, это лучшее, что вы можете сделать.

Наконец, мне также кажется странным, что вы позволите коммитам слияния передаваться другим реферам, но не хозяину. Это может привести к некоторым сюрпризам: если кто-то протолкнет нестабильную ветку, она будет проверена, то вы захотите ее на главном сервере - но не можете ее туда вставить!

2 голосов
/ 30 марта 2011

После долгой борьбы на сервере sourceforge вот что я получил:

#!/bin/sh
# Author: Mathieu Malaterre
# This code is free software. It can be used and distributed under the
# same terms as git itself.
# /7668994/kak-izbezhat-obedinit-vetku-master-iz-ssh-gdcm-git-sourceforge-net-gitroot-gdcm-gdcm
read rev_old rev_new refname

ref_to_check="refs/heads/master"

if [ "$refname" = "$ref_to_check" ]
then
  merge_bases=`git merge-base ${rev_old} ${rev_new}`
  if [ "$merge_bases" != "$rev_old" ]
  then
    echo "Non fastward is disallowed"
    exit 1
  fi
  # non-fast-forward case:
  git rev-list --parents $merge_bases..$rev_new \
    | while read x; do
      set -- $x
      if [ "$#" != "2" ]
      then
        echo "Multiple parents: $x";
        exit 1
      fi;
    done
  [ $? -ne 0 ] && exit 1
fi
exit 0
0 голосов
/ 10 мая 2019

Этот скрипт работал на меня! Защищает выбранные ветви от принудительного нажатия и удаляет.

#!/bin/sh

_REFNAME="$(echo "${1}" | sed -e 's,[^/]\+/,,g')"
_OLDREF="${2}"
_NEWREF="${3}"

_PROTECTED_LIST=( 'master' 'develop' )

_PROTECTED=false
for ref in "${_PROTECTED_LIST[@]}"; do
   if [[ "${ref}" == "${_REFNAME}" ]]; then
      _PROTECTED=true
   fi;
done;

echo ""
echo "#################### YOUR PROJECT NAME ####################"
echo "Branch: ${_REFNAME}"
echo "Old ref: ${_OLDREF}"
echo "New ref: ${_NEWREF}"
echo ""

_SUCCESS=true
if ${_PROTECTED}; then
   _GITOUT="$(git merge-base ${_OLDREF} ${_NEWREF} 2>/dev/null)"
   if [[ -n "${_GITOUT}" && "${_GITOUT}" != "${_OLDREF}" ]]; then
      echo "ERROR! You can't force the push on this branch!"
      _SUCCESS=false
   fi;
   if [[ -n "$(echo "${_NEWREF}" | sed -n -e '/^0\+$/p')" ]]; then
      echo "ERROR! You can't delete this branch!"
      _SUCCESS=false
   fi;
fi;

if ${_SUCCESS}; then
   echo "SUCCESS! :-)"
   echo "See you later?"
   echo ""
   exit 0
fi;

echo ""
exit 1

...