work - ¿Es posible tener un.gitignore personalizado? ¿Acceso de solo lectura?
gitignore node_modules (5)
- Coloque sus reglas de ignorar privadas en
.git/info/exclude
. Vergitignore(5)
. - Para el acceso de solo lectura, use
git-daemon
, un servidor web o Gitosis o Gitolite.
Estoy trabajando en un entorno de equipo, y ya hay un archivo .gitignore
.
Quiero agregar más elementos al archivo .gitignore
, pero tampoco quiero verificar este archivo. Es posible establecer archivos de ignorar personalizados que solo se aplican a mí?
Además, quiero que alguien solo lea el acceso a un repositorio privado de git en nuestro servidor, si agrego su clave SSH a nuestro servidor obtendrán acceso completo como todos los demás. ¿Cómo puedo limitarlo a solo lectura, sin commits permitidos?
Como dijo Fred Frodo, puedes poner tus reglas privadas de exclusión en .git/info/exclude
del repositorio.
Si desea aplicar las mismas reglas de exclusión a todos los repositorios en su máquina, puede agregar lo siguiente al archivo .gitconfig
en su directorio de usuario.
[core]
excludesfile = /home/<myusername>/.gitexclude
A continuación, agregue sus patrones de exclusión a ~/.gitexclude
.
Para la parte ssh, debe considerar usar Gitolite (un reemplazo para la gitosis).
Puede que le interese un gancho de actualización que Junio escribió y que Carl mejoró. 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 gancho en su lugar, le da a los usuarios o grupos particulares para realizar cambios en el repositorio. Cualquier otra persona que pueda verlo tiene acceso de solo lectura.
Esto utiliza dos archivos,
$GIT_DIR/info/allowed-users
yallowed-groups
, para describir qué cabezales pueden ser empujados 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 ramas
bw/penguin
obw/zebra
obw/panda
, Pasky solo puede hacercogito
, y JC puede hacer ramasmaster
ypu
y crear etiquetas versionadas. Y cualquiera puede hacertmp/blah
branches. El signo ''+'' en el registro depu
significa que JC puede hacer empujes no rápidos hacia adelante.
Si esta persona aún no tiene acceso al host donde vive su repositorio, tal vez esa persona solo debe tener acceso a git-shell
lugar de acceso sin restricciones. Cree un usuario de git para fines especiales y en ~git/.ssh/authorized_keys
, agregue la clave SSH del externo en el siguiente formulario. 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 deba ajustar la ruta de acceso a git-shell
. Recuerde que sshd
es altamente paranoico con respecto a los permisos del directorio .ssh
, así que apague sus bits de escritura grupal y todos los archivos debajo de él.
El canalizar a todos a través del usuario de git significa que debes poder distinguir a las personas, y este es el propósito de la variable de entorno myorg_git_user
. En lugar de confiar en un username=$(id -u -n)
incondicional username=$(id -u -n)
, ajuste 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 parecido al siguiente. 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á hacer 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''
Dijiste que estás trabajando en un entorno de equipo, así que supongo que tu repositorio central se creó con la opción - --shared
. (Consulte core.sharedRepository
en la documentación de git config
y --shared
en la documentación de git init
.) 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.
Sé que llego un poco tarde a la conversación pero es posible que desee considerar usar
git update-index --assume-unchanged [ FILE ]
Como dice el documento de ayuda de git:
Cuando el bit "asumir sin cambios" está activado , git deja de verificar los archivos de árbol de trabajo para posibles modificaciones , por lo que debe desarmar manualmente el bit para indicarle a git cuando cambie el archivo de árbol de trabajo ...
Énfasis mío Continúa para decir
Esta opción se puede ... usar como un mecanismo de nivel de archivo grosero para ignorar los cambios no confirmados en los archivos rastreados (similar a lo que hace .gitignore para los archivos no rastreados). Git fallará (correctamente) en caso de que necesite modificar este archivo en el índice, por ejemplo, al fusionarse en una confirmación; por lo tanto, en caso de que el archivo asumido no rastreado se cambie en sentido ascendente, deberá manejar la situación manualmente .
Así que ten en cuenta que deberás conocer cualquier cambio en la cadena ascendente de estos archivos.
En caso de que quiera comenzar a rastrear el archivo nuevamente, todo lo que tiene que hacer es usar
git update-index --no-assume-unchange [ FILE ]
Espero que esto ayude a los futuros espectadores de esta publicación.