Puede que le interese un update hook que Junio escribió y que mejoró Carl. Coloque el código a continuación en $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 enganche en su lugar, le permite a determinados usuarios o grupos realizar cambios en el repositorio. Cualquier otra persona que pueda verlo tiene acceso de solo lectura.
Este utiliza dos archivos, $GIT_DIR/info/allowed-users
y allowed-groups
, para describir que se dirige puede ser empujado a 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 registro pu
significa que JC puede realizar impulsos no rápidos hacia adelante.
Si esta persona no tiene ya acceso al host donde vive su repositorio, tal vez esa persona debe tener solamente git-shell
acceso en lugar de un acceso sin restricciones. Cree un usuario de git de propósito especial y en ~git/.ssh/authorized_keys
, agregue la clave SSH del externo de la siguiente forma. Tenga en cuenta que la clave debe estar en una línea larga, pero la he incluido a continuación para ayudar a la presentación.
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== [email protected]
Dependiendo de su configuración local, es posible que tenga que ajustar la ruta de acceso a git-shell
. Recuerde que sshd
es altamente paranoico con respecto a los permisos del directorio .ssh
, por lo que debe desactivar sus bits de escritura de grupo y todos los archivos debajo de él.
Canalizar a todos a través del usuario git significa que necesita poder distinguir a las personas, y este es el propósito de la variable de entorno myorg_git_user
.En lugar de confiar en una incondicional username=$(id -u -n)
, ajustar 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 sólo lectura será clonar con un comando parecido a la de abajo. La ruta particular dependerá de su configuración. Para que la buena ruta funcione, reubique su repositorio en el directorio de inicio del usuario de git o cree un enlace simbólico que lo señale.
$ git clone [email protected]:coolproject.git
pero no podrá realizar actualizaciones.
$ git push origin mybranch
Total 0 (delta 0), reused 0 (delta 0)
remote: error: hook declined to update refs/heads/mybranch
To [email protected]:coolproject.git
! [remote rejected] mybranch -> mybranch (hook declined)
error: failed to push some refs to '[email protected]:coolproject.git'
Usted dijo que está trabajando en un ambiente de equipo, así que supongo que su repositorio central fue creado con la opción --shared
. (Consulte core.sharedRepository
en git config
documentation y --shared
en el git init
documentation). Asegúrese de que el nuevo usuario de git sea miembro del grupo de sistemas que le da acceso a todos a su repositorio central.
Posible duplicado de [¿Puedo hacer un archivo de gitignore específico del usuario?] (https://stackoverflow.com/questions/5724455/can-i-make-a-user-specific-gitignore-file) –