web-dev-qa-db-fra.com

Est-il possible d'avoir un .gitignore personnalisé? Accès en lecture seule?

Je travaille en équipe et il existe déjà un .gitignore fichier.

Je souhaite ajouter d'autres éléments au .gitignore fichier, mais je ne veux pas non plus archiver ce fichier. Il est possible de définir des fichiers ignorés personnalisés qui ne s'appliquent qu'à moi?

De plus, je veux donner à quelqu'un un accès en lecture seule à un référentiel git privé sur notre serveur, si j'ajoute sa clé SSH à notre serveur, il obtiendra un accès complet comme tout le monde. Comment puis-je le limiter à la lecture seule, aucun commit autorisé.

74
Blankman
  1. Mettez vos règles privées d'ignorance dans .git/info/exclude. Voir gitignore(5) .
  2. Pour un accès en lecture seule, utilisez git-daemon , un serveur Web , ou Gitosis, ou Gitolite.
112
Fred Foo

Je sais que je suis un peu en retard dans la conversation, mais vous voudrez peut-être envisager d'utiliser

git update-index --assume-unchanged [ FILE ]

Comme l'indique le document d'aide de git:

Lorsque le bit "supposer inchangé" est activé, git arrête de vérifier les fichiers de l'arborescence de travail pour d'éventuelles modifications, vous devez donc désactiver manuellement le bit pour indiquer à git lorsque vous modifiez le fichier de l'arborescence de travail ...

Je souligne. Il poursuit en disant

Cette option peut être ... tilisée comme mécanisme grossier au niveau des fichiers pour ignorer les modifications non validées dans les fichiers suivis (semblable à ce que fait .gitignore pour les fichiers non suivis). Git échouera (gracieusement) au cas où il aurait besoin de modifier ce fichier dans l'index, par ex. lors de la fusion dans un commit; ainsi, dans le cas où le fichier supposé non suivi est modifié en amont, vous devrez gérer la situation manuellement.

Gardez donc à l'esprit que vous devrez être au courant des modifications apportées en amont à ces fichiers.

Si vous souhaitez recommencer le suivi du fichier, il vous suffit d'utiliser

git update-index --no-assume-unchange [ FILE ]

J'espère que cela aidera les futurs téléspectateurs de ce message.

18
Jake Greene

Pour la partie ssh, vous devriez envisager d'utiliser Gitolite (un remplacement pour la gitose).

2
Simon

Comme l'a dit Fred Frodo, vous pouvez mettre vos règles d'exclusion privées dans le .git/info/exclude du référentiel.

Si vous souhaitez appliquer les mêmes règles d'exclusion à tous les référentiels de votre machine, vous pouvez ajouter ce qui suit au .gitconfig fichier dans votre répertoire utilisateur.

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

Ajoutez ensuite vos modèles d'exclusion à ~/.gitexclude.

1
Jesse Hogan

Vous pourriez être intéressé par un mise à jour du crochet que Junio ​​a écrit et que Carl a amélioré. Placez le code ci-dessous dans $GIT_DIR/hooks/update Et n'oubliez pas de l'activer avec 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"

Avec ce crochet en place, vous donnez ensuite des utilisateurs ou des groupes particuliers pour apporter des modifications au référentiel. Quiconque peut le voir a un accès en lecture seule.

Celui-ci utilise deux fichiers, $GIT_DIR/info/allowed-users Et allowed-groups, Pour décrire quelles têtes peuvent être poussées par qui. Le format de chaque fichier ressemblerait à ceci:

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

Avec cela, Linus peut pousser ou créer des branches bw/penguin Ou bw/zebra Ou bw/panda, Pasky ne peut faire que cogito et JC peut faire master et pu branches et créer des balises versionnées. Et tout le monde peut faire des branches tmp/blah. Le signe "+" à l'enregistrement pu signifie que JC peut effectuer des poussées non rapides sur celui-ci.

Si cette personne n'a pas déjà accès à l'hôte où réside votre référentiel, cette personne ne devrait peut-être avoir qu'un accès git-Shell Plutôt qu'un accès illimité. Créez un utilisateur git spécial et dans ~git/.ssh/authorized_keys, Ajoutez la clé SSH de l'outsider sous la forme suivante. Notez que la clé doit être sur une longue ligne, mais je l'ai enveloppée ci-dessous pour faciliter la présentation.

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]

Selon votre configuration locale, vous devrez peut-être ajuster le chemin d'accès à git-Shell. N'oubliez pas que sshd est très paranoïaque à propos des autorisations du répertoire .ssh, Désactivez donc ses bits d'écriture de groupe et tous les fichiers en dessous.

En canalisant tout le monde via l'utilisateur git, vous devez pouvoir distinguer les gens, et c'est le but de la variable d'environnement myorg_git_user. Au lieu de compter sur une username=$(id -u -n) inconditionnelle, ajustez votre hook de mise à jour pour l'utiliser:

# 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'"

Avec cette configuration, votre ami avec accès en lecture seule clone avec une commande ressemblant à celle ci-dessous. Le chemin particulier dépendra de votre configuration. Pour que le chemin Nice fonctionne, déplacez votre référentiel dans le répertoire personnel de l'utilisateur git ou créez un lien symbolique qui pointe vers celui-ci.

$ git clone [email protected]: coolproject.git

mais ne pourra pas faire de mises à jour.

$ git Push Origin mybranch 
 Total 0 (delta 0), réutilisé 0 (delta 0) 
 remote: erreur: le crochet a refusé de mettre à jour refs/heads/mybranch 
 To git @ blankman .com.invalid: coolproject.git 
! [Rejeté à distance] mybranch -> mybranch (crochet refusé) 
 erreur: échec de l'envoi de quelques références à '[email protected]: coolproject.git'

Vous avez dit que vous travaillez dans un environnement d'équipe, donc je suppose que votre référentiel central a été créé avec l'option --shared. (Voir core.sharedRepository Dans la documentation git config et --shared Dans la documentation git init .) assurez-vous que le nouvel utilisateur git est membre du groupe système qui vous donne tous accès à votre référentiel central.

0
Greg Bacon