Puede que le interese un gancho de actualización que escribió Junio y que Carl mejoró. Coloque el código a continuación $GIT_DIR/hooks/update
y no olvide habilitarlo con 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"
Con este gancho en su lugar, entonces le da a usuarios o grupos particulares para realizar cambios en el repositorio. Cualquier otra persona que pueda verlo tiene acceso de solo lectura.
Esto usa dos archivos, $GIT_DIR/info/allowed-users
y allowed-groups
, para describir qué cabezas pueden ser empujadas por quién. El formato de cada archivo se vería así:
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
Con esto, Linus puede empujar o crear bw/penguin
o bw/zebra
o bw/panda
ramas, Pasky sólo puede hacer cogito
, y JC puede hacer master
y pu
ramas y hacer etiquetas versionados. Y cualquiera puede hacer tmp/blah
ramas. El signo '+' en el pu
registro significa que JC puede hacer empujones que no sean de avance rápido.
Si esta persona aún no tiene acceso al host donde vive su repositorio, tal vez esa persona debería tener solo git-shell
acceso en lugar de acceso no restringido. Cree un usuario de git de propósito especial y ~git/.ssh/authorized_keys
agregue la clave SSH del forastero en el siguiente formulario. Tenga en cuenta que la clave debe estar en una línea larga, pero la he envuelto a continuación para facilitar la presentación.
sin reenvío de agentes, sin reenvío de puertos, sin pty, sin reenvío X11,
command = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
\ "$ {SSH_ORIGINAL_COMMAND: -} \" "ssh-rsa AAAAB3 ... 2iQ == joeuser@foo.invalid
Dependiendo de su configuración local, es posible que deba ajustar la ruta a git-shell
. Recuerde que sshd
es muy paranoico acerca de los permisos del .ssh
directorio, así que desactive sus bits de escritura de grupo y todos los archivos debajo de él.
Canalizar a todos a través del usuario de git significa que debe poder diferenciar a las personas, y este es el propósito de la myorg_git_user
variable de entorno. En lugar de depender de un incondicional username=$(id -u -n)
, modifique su gancho de actualización para usarlo:
# 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'"
Con esta configuración, su amigo con acceso de solo lectura se clonará con un comando similar al siguiente. La ruta particular dependerá de su configuración. Para que la ruta agradable funcione, reubique su repositorio en el directorio de inicio del usuario de git o cree un enlace simbólico que apunte a él.
$ git clone git@blankman.com.invalid: coolproject.git
pero no podrá realizar actualizaciones.
$ git push origin mybranch
Total 0 (delta 0), reutilizado 0 (delta 0)
remoto: error: el gancho se negó a actualizar refs / heads / mybranch
Para git@blankman.com.invalid: coolproject.git
! [remoto rechazado] mybranch -> mybranch (gancho rechazado)
error: no se pudieron enviar algunas referencias a 'git@blankman.com.invalid: coolproject.git'
Dijiste que estás trabajando en un entorno de equipo, así que supongo que tu repositorio central se creó con la --shared
opción. (Vea core.sharedRepository
en la git config
documentación y --shared
en la git init
documentación ). Asegúrese de que el nuevo usuario de git sea miembro del grupo del sistema que les da acceso a todos a su repositorio central.