¿Es posible tener un .gitignore personalizado? ¿Acceso de solo lectura?

79

Estoy trabajando en un entorno de equipo y ya existe un .gitignorearchivo.

Quiero agregar más elementos al .gitignorearchivo, pero tampoco quiero verificar este archivo. ¿Es posible configurar archivos personalizados para ignorar que solo se aplican a mí?

Además, quiero darle a alguien acceso de solo lectura 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, no se permiten confirmaciones?

Blankman
fuente

Respuestas:

122
  1. Ponga sus reglas privadas de ignorar .git/info/exclude. Ver gitignore(5).
  2. Para acceso de solo lectura, utilice git-daemonun servidor web o Gitosis o Gitolite.
Fred Foo
fuente
y para empeorar las cosas, quiero que este gitignore sea para un proyecto específico, no para un entorno global.
Blankman
7
@Blankman: colóquelo .git/info/exclude en el directorio raíz del proyecto .
Fred Foo
1
Hágalo completo: con la opción de configuración core.excludesfilepuede especificar un archivo de exclusiones globales .
KingCrunch
1
Para cualquier instalación nueva, estoy de acuerdo con Simon, debes usar gitolite en lugar de gitosis.
ebneter
1
Una forma útil de usar esto: Primero -> ln -s .git/info/exclude .personalGitignoreLuego podemos agregar # ln -s .git/info/exclude .personalGitignore \n .personalGitignorea .gitignore
Josu Goñi
18

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 comprobar los archivos del árbol de trabajo en busca de posibles modificaciones , por lo que debe desarmar manualmente el bit para decirle a git cuando cambie el archivo del árbol de trabajo ...

Énfasis mío. Continúa diciendo

Esta opción se puede ... utilizar como un mecanismo de nivel de archivo burdo para ignorar los cambios no confirmados en los archivos rastreados (similar a lo que hace .gitignore para los archivos no rastreados). Git fallará (con gracia) en caso de que necesite modificar este archivo en el índice, por ejemplo, cuando se fusiona en una confirmación; por lo tanto, en caso de que el archivo supuesto sin seguimiento se cambie en sentido ascendente, deberá manejar la situación manualmente .

Por lo tanto, tenga en cuenta que deberá estar al tanto de cualquier cambio anterior realizado en estos archivos.

En el caso de que desee 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.

Jake Greene
fuente
2

Para la parte ssh, debería considerar usar Gitolite (un reemplazo de la gitosis).

Simón
fuente
2

Como dijo Fred Frodo, puede poner sus reglas de exclusión privadas en .git/info/excludeel repositorio.

Si desea aplicar las mismas reglas de exclusión a todos los repositorios de su máquina, puede agregar lo siguiente al .gitconfigarchivo en su directorio de usuario.

[core]       
    excludesfile = /home/<myusername>/.gitexclude 

Luego agregue sus patrones de exclusión a ~/.gitexclude.

Jesse Hogan
fuente
1

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/updatey 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-usersy 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/penguino bw/zebrao bw/pandaramas, Pasky sólo puede hacer cogito, y JC puede hacer mastery puramas y hacer etiquetas versionados. Y cualquiera puede hacer tmp/blahramas. El signo '+' en el puregistro 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-shellacceso en lugar de acceso no restringido. Cree un usuario de git de propósito especial y ~git/.ssh/authorized_keysagregue 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 == [email protected]

Dependiendo de su configuración local, es posible que deba ajustar la ruta a git-shell. Recuerde que sshdes muy paranoico acerca de los permisos del .sshdirectorio, 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_uservariable 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 [email protected]: 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 [email protected]: coolproject.git
 ! [remoto rechazado] mybranch -> mybranch (gancho rechazado)
error: no se pudieron enviar algunas referencias a '[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 --sharedopción. (Vea core.sharedRepositoryen la git configdocumentación y --shareden la git initdocumentació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.

Greg Bacon
fuente