Możesz być zainteresowany hakiem do aktualizacji, który napisał Junio i który Carl ulepszył. Umieść poniższy kod w $GIT_DIR/hooks/update
i nie zapomnij go włączyć za pomocą 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"
Mając ten zaczep na miejscu, dajesz określonym użytkownikom lub grupom wprowadzenie zmian w repozytorium. Każdy, kto może go zobaczyć, ma dostęp tylko do odczytu.
Używa to dwóch plików $GIT_DIR/info/allowed-users
i allowed-groups
, aby opisać, które głowy mogą zostać przez kogo wepchnięte. Format każdego pliku wyglądałby następująco:
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
Dzięki temu Linus może wypychać lub tworzyć bw/penguin
lub bw/zebra
lub bw/panda
rozgałęzienia, Pasky może to robić tylko cogito
, a JC może robić master
i pu
rozgałęziać i tworzyć wersjonowane znaczniki. I każdy może robić tmp/blah
gałęzie. Znak „+” przy pu
rekordzie oznacza, że JC może go przesuwać bez przewijania do przodu.
Jeśli ta osoba nie ma jeszcze dostępu do hosta, na którym znajduje się Twoje repozytorium, może powinna mieć tylko git-shell
dostęp, a nie nieograniczony dostęp. Utwórz specjalnego użytkownika git i ~git/.ssh/authorized_keys
dodaj klucz SSH osoby z zewnątrz w następującym formularzu. Zauważ, że klucz powinien znajdować się w jednej długiej linii, ale zawinąłem go poniżej, aby ułatwić prezentację.
przekazywanie bez agenta, przekazywanie bez portów, przekazywanie bez pty, przekazywanie bez X11,
command = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
\ "$ {SSH_ORIGINAL_COMMAND: -} \" "ssh-rsa AAAAB3 ... 2iQ == joeuser@foo.invalid
W zależności od konfiguracji lokalnej może być konieczne dostosowanie ścieżki do git-shell
. Pamiętaj, że sshd
jest to bardzo paranoiczne w kwestii uprawnień do .ssh
katalogu, więc wyłącz jego bity zapisu grupowego i wszystkie pliki poniżej.
Prowadzenie wszystkich przez użytkownika git oznacza, że musisz umieć rozróżniać ludzi i taki jest cel myorg_git_user
zmiennej środowiskowej. Zamiast polegać na bezwarunkowym username=$(id -u -n)
, dostosuj swój hak do aktualizacji, aby go używać:
# 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'"
W tej konfiguracji znajomy z dostępem tylko do odczytu zostanie sklonowany poleceniem podobnym do poniższego. Konkretna ścieżka będzie zależeć od konfiguracji. Aby ładna ścieżka działała, przenieś swoje repozytorium do katalogu domowego użytkownika git lub utwórz dowiązanie symboliczne, które na nie wskazuje.
$ git clone git@blankman.com.invalid: coolproject.git
ale nie będzie w stanie dokonywać aktualizacji.
$ git push origin mybranch
Razem 0 (delta 0), ponownie wykorzystane 0 (delta 0)
remote: error: hook odmówił aktualizacji refs / heads / mybranch
Do git@blankman.com.invalid: coolproject.git
! [zdalne odrzucenie] mybranch -> mybranch (hak odrzucony)
błąd: nie udało się przesłać niektórych odnośników do „git@blankman.com.invalid: coolproject.git”
Powiedziałeś, że pracujesz w środowisku zespołowym, więc zakładam, że Twoje centralne repozytorium zostało utworzone z tą --shared
opcją. (Patrz core.sharedRepository
w git config
dokumentacji oraz --shared
w git init
dokumentacji ). Upewnij się, że nowy użytkownik git jest członkiem grupy systemu, który daje wam wszystkim dostęp do centralnego repozytorium.