Czy można mieć niestandardowy plik .gitignore? Dostęp tylko do odczytu?

79

Pracuję w środowisku zespołowym i jest już .gitignoreplik.

Chcę dodać więcej elementów do .gitignorepliku, ale nie chcę też sprawdzać tego pliku. Czy można ustawić niestandardowe ignorowanie plików, które dotyczą tylko mnie?

Chcę też dać komuś dostęp tylko do odczytu do prywatnego repozytorium git na naszym serwerze, jeśli dodam jego klucz SSH do naszego serwera, otrzyma pełny dostęp, jak wszyscy inni. Jak mogę ograniczyć to tylko do odczytu, bez zatwierdzeń.

Blankman
źródło

Odpowiedzi:

122
  1. Umieść swoje prywatne zasady ignorowania .git/info/exclude. Zobacz gitignore(5).
  2. Dla dostępem tylko do odczytu, użytkowania git-daemon, a serwerem WWW lub Gitosis lub Gitolite.
Fred Foo
źródło
Co gorsza, chcę, aby ten gitignore był przeznaczony do konkretnego projektu, a nie do globalnego ustawienia.
Blankman
7
@Blankman: umieść to w .git/info/exclude katalogu głównym projektu .
Fred Foo
1
Uzupełnij wszystko: dzięki opcji config core.excludesfilemożesz określić globalny plik wykluczeń.
KingCrunch
1
Zgadzam się z Simonem przy każdej nowej instalacji, powinieneś raczej używać gitolite niż gitosis.
ebneter
1
Przydatny sposób korzystania z tego: Najpierw -> ln -s .git/info/exclude .personalGitignoreNastępnie możemy dodać # ln -s .git/info/exclude .personalGitignore \n .personalGitignoredo .gitignore
Josu Goñi
18

Wiem, że trochę się spóźniłem na rozmowę, ale warto rozważyć użycie

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

Jak stwierdza dokument pomocy git:

Kiedy bit "zakładaj niezmieniony" jest włączony, git przestaje sprawdzać pliki drzewa roboczego pod kątem możliwych modyfikacji , więc musisz ręcznie usunąć ten bit, aby poinformować git o zmianie pliku drzewa roboczego ...

Podkreśl moje. Dalej mówi

Ta opcja może być ... użyta jako zgrubny mechanizm na poziomie pliku do ignorowania niezatwierdzonych zmian w śledzonych plikach (podobnie jak .gitignore robi dla plików nieśledzonych). Git zawiedzie (z wdziękiem) w przypadku konieczności zmodyfikowania tego pliku w indeksie, np. Przy scalaniu w zatwierdzeniu; w związku z tym w przypadku, gdy plik, który zakłada się, że nie jest śledzony, zostanie zmieniony przez nadawcę, będziesz musiał ręcznie obsłużyć sytuację .

Pamiętaj więc, że będziesz musiał być świadomy wszelkich zmian wprowadzonych do tych plików.

W przypadku, gdy chcesz ponownie rozpocząć śledzenie pliku, wystarczy użyć

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

Mam nadzieję, że pomoże to przyszłym widzom tego posta.

Jake Greene
źródło
2

W przypadku części ssh należy rozważyć użycie Gitolite (zamiennik gitozy).

Szymon
źródło
2

Jak powiedział Fred Frodo, możesz umieścić swoje prywatne reguły wykluczania w .git/info/excluderepozytorium.

Jeśli chcesz zastosować te same reguły wykluczania do wszystkich repozytoriów na swoim komputerze, możesz dodać następujące elementy do .gitconfigpliku w katalogu użytkownika.

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

Następnie dodaj swoje wzorce wykluczania do ~/.gitexclude.

Jesse Hogan
źródło
1

Możesz być zainteresowany hakiem do aktualizacji, który napisał Junio ​​i który Carl ulepszył. Umieść poniższy kod w $GIT_DIR/hooks/updatei nie zapomnij go włączyć za pomocą 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"

Mając ten zaczep na miejscu, dajesz określonym użytkownikom lub grupom wprowadzenie zmian w repozytorium. Każdy, kto może go zobaczyć, ma dostęp tylko do odczytu.

Używa to dwóch plików $GIT_DIR/info/allowed-usersi allowed-groups, aby opisać, które głowy mogą zostać przez kogo wepchnięte. Format każdego pliku wyglądałby następująco:

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

Dzięki temu Linus może wypychać lub tworzyć bw/penguinlub bw/zebralub bw/pandarozgałęzienia, Pasky może to robić tylko cogito, a JC może robić masteri purozgałęziać i tworzyć wersjonowane znaczniki. I każdy może robić tmp/blahgałęzie. Znak „+” przy purekordzie oznacza, że ​​JC może go przesuwać bez przewijania do przodu.

Jeśli ta osoba nie ma jeszcze dostępu do hosta, na którym znajduje się Twoje repozytorium, może powinna mieć tylko git-shelldostęp, a nie nieograniczony dostęp. Utwórz specjalnego użytkownika git i ~git/.ssh/authorized_keysdodaj klucz SSH osoby z zewnątrz w następującym formularzu. Zauważ, że klucz powinien znajdować się w jednej długiej linii, ale zawinąłem go poniżej, aby ułatwić prezentację.

przekazywanie bez agenta, przekazywanie bez portów, przekazywanie bez pty, przekazywanie bez X11,
command = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
\ "$ {SSH_ORIGINAL_COMMAND: -} \" "ssh-rsa AAAAB3 ... 2iQ == [email protected]

W zależności od konfiguracji lokalnej może być konieczne dostosowanie ścieżki do git-shell. Pamiętaj, że sshdjest to bardzo paranoiczne w kwestii uprawnień do .sshkatalogu, więc wyłącz jego bity zapisu grupowego i wszystkie pliki poniżej.

Prowadzenie wszystkich przez użytkownika git oznacza, że ​​musisz umieć rozróżniać ludzi i taki jest cel myorg_git_userzmiennej środowiskowej. Zamiast polegać na bezwarunkowym username=$(id -u -n), dostosuj swój hak do aktualizacji, aby go używać:

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

W tej konfiguracji znajomy z dostępem tylko do odczytu zostanie sklonowany poleceniem podobnym do poniższego. Konkretna ścieżka będzie zależeć od konfiguracji. Aby ładna ścieżka działała, przenieś swoje repozytorium do katalogu domowego użytkownika git lub utwórz dowiązanie symboliczne, które na nie wskazuje.

$ git clone [email protected]: coolproject.git

ale nie będzie w stanie dokonywać aktualizacji.

$ git push origin mybranch 
Razem 0 (delta 0), ponownie wykorzystane 0 (delta 0)
remote: error: hook odmówił aktualizacji refs / heads / mybranch
Do [email protected]: coolproject.git
 ! [zdalne odrzucenie] mybranch -> mybranch (hak odrzucony)
błąd: nie udało się przesłać niektórych odnośników do „[email protected]: coolproject.git”

Powiedziałeś, że pracujesz w środowisku zespołowym, więc zakładam, że Twoje centralne repozytorium zostało utworzone z tą --sharedopcją. (Patrz core.sharedRepositoryw git configdokumentacji oraz --sharedw git initdokumentacji ). Upewnij się, że nowy użytkownik git jest członkiem grupy systemu, który daje wam wszystkim dostęp do centralnego repozytorium.

Greg Bacon
źródło