Я хотел бы защитить свой репозиторий git, чтобы можно было перезаписать только неосновные ветки. Есть ли способ защитить только выбранные ветки?
Как я могу предотвратить небыстрые нажатия на выбранные ветки в git?
Ответы (7)
Вы можете использовать GitEnterprise для настройки разрешений для каждой ветки (администратора) для блокировки не-fastforward push-уведомлений с использованием детального разрешения доступа. .
И git config --system receive.denyNonFastForwards true
просто выполнит эту работу, если вам нужно заблокировать изменение истории для всех веток.
local
поверх удаленного мастера и объедините ее с мастером. Всегда вперед.
- person Sergey K.; 03.09.2016
Вот хук обновления (копировать в хуки/обновление), который я написал для собственного использования. Этот сценарий по умолчанию запрещает все обновления без быстрой перемотки вперед, но разрешает их для явно настроенных ветвей. Должно быть достаточно легко инвертировать его, чтобы обновления без быстрой перемотки вперед были разрешены для всех, кроме главной ветки.
#!/bin/sh
#
# A hook script to block non-fast-forward updates for branches that haven't
# been explicitly configured to allow it. Based on update.sample.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# Config
# ------
# hooks.branch.<name>.allownonfastforward
# This boolean sets whether non-fast-forward updates will be allowed for
# branch <name>. By default they won't be.
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
;;
refs/tags/*,delete)
# delete tag
;;
refs/tags/*,tag)
# annotated tag
;;
refs/heads/*,commit)
# branch
# git rev-list doesn't print anything on fast-forward updates
if test $(git rev-list "$newrev".."$oldrev"); then
branch=${refname##refs/heads/}
nonfastforwardallowed=$(git config --bool hooks.branch."$branch".allownonfastforward)
if [ "$nonfastforwardallowed" != "true" ]; then
echo "hooks/update: Non-fast-forward updates are not allowed for branch $branch"
exit 1
fi
fi
;;
refs/heads/*,delete)
# delete branch
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
;;
*)
# Anything else (is there anything else?)
echo "hooks/update: Unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0
Вы можете предотвратить обновления без быстрой перемотки вперед, настроив denyNonFastForwards
git config --system receive.denyNonFastForwards true
Но это относится ко всем отраслям. Для получения дополнительной информации см. ProGit.
Я думаю, это зависит от того, что вы используете на стороне сервера для доступа к вашему репозиторию. Некоторые серверные приложения поддерживают разрешения для каждой ветки, например Gerrit или Gitlab (однако я не уверен, поддерживает ли Gitlab ваш вариант использования). Gerrit поддерживает это, так как я использую аналогичный рабочий процесс в своей компании.
Возможно, Gitolite также поддерживает его (это то, что Gitlab использует под капотом), который проще в настройке, но не нет веб-интерфейса, такого как Gerrit или Gitlab.
Дополнительный комментарий: GitEnterprise, как было предложено, также является хорошим решением, однако мои предложения подходят, если у вас есть собственный сервер (что распространено во многих компаниях).
Если вам будет разрешено изменить свой сервер, это позволит выполнять быструю перемотку на сервере.
ssh ip 'echo $"[receive]
denyDeletes = false
denyNonFastForwards = false" >> /path/to/repo/config'
#then git push -f origin master
Этот ответ SO даст вам то, что вы ищете. Просто отредактируйте его, чтобы применить его к основной ветке:
#!/bin/sh
# lock the master branch for pushing
refname="$1"
if [ "$refname" = "refs/heads/master" ]
then
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
echo "You cannot push to the master branch."
echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
exit 1
fi
exit 0
Обновление:
Это предотвратит все отправки в основную ветку, включая ускоренную перемотку вперед.
Вот модификация сценария Tanu Kaskinen, позволяющая использовать подстановочные знаки для имен ветвей. Мы используем ветки с именами, начинающимися с «d/», для обозначения веток «разработки». Я хотел разрешить обновления без перемотки вперед для этих веток d/:
refs/heads/*,commit)
# branch
# git rev-list doesn't print anything on fast-forward updates
if [[ $(git rev-list "$newrev".."$oldrev") ]]; then
branch=${refname##refs/heads/}
if [[ "$branch" =~ ^d/ ]] ; then
echo "Non-fast-forward update allowed on d/ branch"
nonfastforwardallowed="true";
else
#look for a specific config setting
nonfastforwardallowed=$(git config --bool hooks.branch."$branch".allownonfastforward)
fi
if [ "$nonfastforwardallowed" != "true" ]; then
echo "hooks/update: Non-fast-forward updates are not allowed for branch $branch"
exit 1
fi
fi