Sie könnten an einem Update-Hook interessiert sein , den Junio geschrieben und den Carl verbessert hat. Geben Sie den folgenden Code ein $GIT_DIR/hooks/updateund vergessen Sie nicht, ihn mit zu aktivieren 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"
Mit diesem Hook geben Sie dann bestimmten Benutzern oder Gruppen die Möglichkeit, Änderungen am Repository vorzunehmen. Jeder andere, der es sehen kann, hat nur Lesezugriff.
Dies verwendet zwei Dateien $GIT_DIR/info/allowed-usersund allowed-groups, um zu beschreiben, welche Köpfe von wem hineingeschoben werden können. Das Format jeder Datei würde folgendermaßen aussehen:
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
Damit kann Linus pushen oder erstellen bw/penguinoder bw/zebraoder bw/pandaverzweigen, Pasky kann nur cogitound JC kann masterund puverzweigen und versionierte Tags erstellen . Und jeder kann tmp/blahZweige machen. Das Pluszeichen im puDatensatz bedeutet, dass JC nicht schnell vorwärts drücken kann.
Wenn diese Person noch keinen Zugriff auf den Host hat, auf dem sich Ihr Repository befindet, sollte diese Person möglicherweise nur git-shellZugriff und keinen uneingeschränkten Zugriff haben. Erstellen Sie einen speziellen Git-Benutzer und ~git/.ssh/authorized_keysfügen Sie den SSH-Schlüssel des Außenstehenden in der folgenden Form hinzu. Beachten Sie, dass sich der Schlüssel in einer langen Zeile befinden sollte, aber ich habe ihn unten verpackt, um die Präsentation zu erleichtern.
No-Agent-Weiterleitung, No-Port-Weiterleitung, No-Pty, No-X11-Weiterleitung,
command = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
"$ {SSH_ORIGINAL_COMMAND: -}" ssh-rsa AAAAB3 ... 2iQ == joeuser@foo.invalid
Abhängig von Ihrem lokalen Setup müssen Sie möglicherweise den Pfad zu anpassen git-shell. Denken Sie daran, dass die sshdBerechtigungen des .sshVerzeichnisses sehr paranoid sind. Deaktivieren Sie daher die Gruppenschreibbits und alle darunter liegenden Dateien.
Wenn Sie alle Benutzer durch den Git-Benutzer leiten, müssen Sie in der Lage sein, die Benutzer voneinander zu unterscheiden. Dies ist der Zweck der myorg_git_userUmgebungsvariablen. Anstatt sich auf ein Unbedingtes zu verlassen username=$(id -u -n), optimieren Sie Ihren Update-Hook, um ihn zu verwenden:
# 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'"
Mit diesem Setup klont Ihr Freund mit schreibgeschütztem Zugriff mit einem Befehl, der dem folgenden ähnelt. Der jeweilige Pfad hängt von Ihrem Setup ab. Um den netten Pfad zum Laufen zu bringen, verschieben Sie entweder Ihr Repository in das Home-Verzeichnis des Git-Benutzers oder erstellen Sie einen Symlink, der darauf verweist.
$ git clone git@blankman.com.invalid: coolproject.git
kann aber keine Updates vornehmen.
$ git push origin mybranch
Insgesamt 0 (Delta 0), wiederverwendet 0 (Delta 0)
remote: error: hook lehnte es ab, refs / Heads / Mybranch zu aktualisieren
An git@blankman.com.invalid: coolproject.git
! [remote abgelehnt] mybranch -> mybranch (Haken abgelehnt)
Fehler: Einige Refs konnten nicht an 'git@blankman.com.invalid: coolproject.git' gesendet werden.
Sie sagten, Sie arbeiten in einer Teamumgebung, daher gehe ich davon aus, dass Ihr zentrales Repository mit dieser --sharedOption erstellt wurde. (Siehe core.sharedRepositoryin der git configDokumentation und --sharedin der git initDokumentation .) Stellen Sie sicher, dass der neue Git-Benutzer Mitglied der Systemgruppe ist, die Ihnen allen Zugriff auf Ihr zentrales Repository gewährt.