Вас може зацікавити гачок оновлення, який написав Хуніо і який покращив Карл. Помістіть код нижче $GIT_DIR/hooks/update
і не забудьте увімкнути його за допомогою chmod +x
.
#!/bin/bash
umask 002
# If you are having trouble with this access control hook script
# you can try setting this to true. It will tell you exactly
# why a user is being allowed/denied access.
verbose=false
# Default shell globbing messes things up downstream
GLOBIGNORE=*
function grant {
$verbose && echo >&2 "-Grant- $1"
echo grant
exit 0
}
function deny {
$verbose && echo >&2 "-Deny- $1"
echo deny
exit 1
}
function info {
$verbose && echo >&2 "-Info- $1"
}
# Implement generic branch and tag policies.
# - Tags should not be updated once created.
# - Branches should only be fast-forwarded unless their pattern starts with '+'
case "$1" in
refs/tags/*)
git rev-parse --verify -q "$1" &&
deny >/dev/null "You can't overwrite an existing tag"
;;
refs/heads/*)
# No rebasing or rewinding
if expr "$2" : '0*$' >/dev/null; then
info "The branch '$1' is new..."
else
# updating -- make sure it is a fast-forward
mb=$(git-merge-base "$2" "$3")
case "$mb,$2" in
"$2,$mb") info "Update is fast-forward" ;;
*) noff=y; info "This is not a fast-forward update.";;
esac
fi
;;
*)
deny >/dev/null \
"Branch is not under refs/heads or refs/tags. What are you trying to do?"
;;
esac
# Implement per-branch controls based on username
allowed_users_file=$GIT_DIR/info/allowed-users
username=$(id -u -n)
info "The user is: '$username'"
if test -f "$allowed_users_file"
then
rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
while read heads user_patterns
do
# does this rule apply to us?
head_pattern=${heads#+}
matchlen=$(expr "$1" : "${head_pattern#+}")
test "$matchlen" = ${#1} || continue
# if non-ff, $heads must be with the '+' prefix
test -n "$noff" &&
test "$head_pattern" = "$heads" && continue
info "Found matching head pattern: '$head_pattern'"
for user_pattern in $user_patterns; do
info "Checking user: '$username' against pattern: '$user_pattern'"
matchlen=$(expr "$username" : "$user_pattern")
if test "$matchlen" = "${#username}"
then
grant "Allowing user: '$username' with pattern: '$user_pattern'"
fi
done
deny "The user is not in the access list for this branch"
done
)
case "$rc" in
grant) grant >/dev/null "Granting access based on $allowed_users_file" ;;
deny) deny >/dev/null "Denying access based on $allowed_users_file" ;;
*) ;;
esac
fi
allowed_groups_file=$GIT_DIR/info/allowed-groups
groups=$(id -G -n)
info "The user belongs to the following groups:"
info "'$groups'"
if test -f "$allowed_groups_file"
then
rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
while read heads group_patterns
do
# does this rule apply to us?
head_pattern=${heads#+}
matchlen=$(expr "$1" : "${head_pattern#+}")
test "$matchlen" = ${#1} || continue
# if non-ff, $heads must be with the '+' prefix
test -n "$noff" &&
test "$head_pattern" = "$heads" && continue
info "Found matching head pattern: '$head_pattern'"
for group_pattern in $group_patterns; do
for groupname in $groups; do
info "Checking group: '$groupname' against pattern: '$group_pattern'"
matchlen=$(expr "$groupname" : "$group_pattern")
if test "$matchlen" = "${#groupname}"
then
grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
fi
done
done
deny "None of the user's groups are in the access list for this branch"
done
)
case "$rc" in
grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;;
deny) deny >/dev/null "Denying access based on $allowed_groups_file" ;;
*) ;;
esac
fi
deny >/dev/null "There are no more rules to check. Denying access"
За допомогою цього гачка ви надаєте певним користувачам чи групам можливість вносити зміни до сховища. Будь-хто, хто може бачити його, має доступ лише для читання.
Для цього використовуються два файли $GIT_DIR/info/allowed-users
і allowed-groups
, щоб описати, в які голови хто може заштовхнути. Формат кожного файлу буде виглядати так:
refs/heads/master junio
+refs/heads/pu junio
refs/heads/cogito$ pasky
refs/heads/bw/.* linus
refs/heads/tmp/.* .*
refs/tags/v[0-9].* junio
При цьому, Лінус може штовхати або створювати bw/penguin
або bw/zebra
або bw/panda
гілку, Pasky може зробити тільки cogito
, і JC може зробити master
і pu
гілка і зробити версіровани тег. І будь-хто може робити tmp/blah
гілки. Знак "+" на pu
записі означає, що JC може робити нешвидкі натискання на нього вперед.
Якщо ця особа ще не має доступу до хосту, де живе ваше сховище, можливо, ця особа повинна мати лише git-shell
доступ, а не необмежений доступ. Створіть спеціального користувача git та ~git/.ssh/authorized_keys
додайте сторонній SSH-ключ у наступну форму. Зверніть увагу, що ключ повинен знаходитися на одному довгому рядку, але я обернув його нижче, щоб допомогти презентації.
no-agent-forwarding, no-port-forwarding, no-pty, no-X11-forwarding,
command = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
\ "$ {SSH_ORIGINAL_COMMAND: -} \" "ssh-rsa AAAAB3 ... 2iQ == joeuser@foo.invalid
Залежно від локальних налаштувань, можливо, вам доведеться відкоригувати шлях до git-shell
. Пам'ятайте, що sshd
це дуже параноїчно щодо дозволів .ssh
каталогу, тому вимкніть його біти для групового запису та всі файли під ним.
Спрямування всіх через користувача git означає, що ви повинні вміти розрізняти людей, і в цьому полягає myorg_git_user
змінна середовища. Замість того, щоб покладатися на безумовний username=$(id -u -n)
, налаштуйте гачок оновлення, щоб використовувати його:
# Implement per-branch controls based on username
allowed_users_file=$GIT_DIR/info/allowed-users
if [ -z "$myorg_git_user" ]; then
username=$(id -u -n)
else
username=$myorg_git_user
fi
info "The user is: '$username'"
За допомогою цього налаштування ваш друг із доступом лише для читання клонуватиме команду, схожу на наведену нижче. Конкретний шлях залежатиме від ваших налаштувань. Щоб приємний шлях працював, перенесіть своє сховище в домашній каталог користувача git або створіть символічне посилання, яке вказує на нього.
$ git клон git@blankman.com.invalid: coolproject.git
але не зможе робити оновлення.
$ git push походження mybranch
Всього 0 (дельта 0), повторно використане 0 (дельта 0)
віддалений: помилка: хук відхилений для оновлення refs / heads / mybranch
На адресу git@blankman.com.invalid: coolproject.git
! [віддалено відхилено] mybranch -> mybranch (гачок відхилено)
помилка: не вдалося висунути деякі посилання на 'git@blankman.com.invalid: coolproject.git'
Ви сказали, що працюєте в командному середовищі, тому я припускаю, що ваше центральне сховище було створено за допомогою цієї --shared
опції. (Див core.sharedRepository
в git config
документації і --shared
в git init
документації .) Переконайтеся , що новий користувач мерзотника є членом групи систем , яка дає всім вам доступ до вашого центральному сховищу.