Можно ли создать собственный .gitignore? Доступ только для чтения?

79

Я работаю в команде, а .gitignoreфайл уже есть .

Я хочу добавить в .gitignoreфайл больше элементов , но не хочу проверять и этот файл. Можно ли настроить собственные файлы игнорирования, которые применимы только ко мне?

Кроме того, я хочу предоставить кому-то доступ только для чтения к частному репозиторию git на нашем сервере, если я добавлю их SSH-ключ на наш сервер, они получат полный доступ, как и все остальные. Как я могу ограничить его только для чтения, без коммитов.

Blankman
источник

Ответы:

122
  1. Добавьте свои личные правила игнорирования .git/info/exclude. Смотрите gitignore(5).
  2. Для доступа только для чтения, использования git-daemon, на веб - сервере , или Gitosis или Gitolite.
Фред Фу
источник
и, что еще хуже, я хочу, чтобы этот gitignore использовался для конкретного проекта, а не для глобальной настройки.
Blankman
7
@Blankman: поместите его в .git/info/exclude корневой каталог проекта .
Фред Фу,
1
Завершение: с помощью параметра конфигурации core.excludesfileвы можете указать глобальный файл исключений.
KingCrunch
1
Для любой новой установки, я согласен с Саймоном, вам следует использовать гитолит, а не гитозис.
ebneter
1
Полезный способ использовать это: Сначала -> ln -s .git/info/exclude .personalGitignoreЗатем мы можем добавить # ln -s .git/info/exclude .personalGitignore \n .personalGitignoreв .gitignore
Goñi
18

Я знаю, что немного опаздываю на разговор, но вы можете подумать об использовании

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

Как говорится в справочном документе git:

Когда бит "предполагать неизменным" включен, git перестает проверять файлы рабочего дерева на предмет возможных модификаций , поэтому вам нужно вручную сбросить бит, чтобы сообщить git, когда вы изменяете файл рабочего дерева ...

Акцент мой. Далее говорится

Эту опцию можно ... использовать как грубый механизм на уровне файлов для игнорирования незафиксированных изменений в отслеживаемых файлах (аналогично тому, что делает .gitignore для неотслеживаемых файлов). Git завершится ошибкой (изящно), если потребуется изменить этот файл в индексе, например, при слиянии в фиксации; таким образом, в случае изменения предполагаемого неотслеживаемого файла в восходящем направлении, вам нужно будет обработать ситуацию вручную .

Так что просто имейте в виду, что вам нужно будет знать обо всех изменениях, внесенных в эти файлы.

Если вы хотите снова начать отслеживание файла, все, что вам нужно сделать, это использовать

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

Я надеюсь, что это поможет всем будущим читателям этого поста.

Джейк Грин
источник
2

Что касается ssh, вам следует подумать об использовании Gitolite (замена gitosis).

Саймон
источник
2

Как сказал Фред Фродо, вы можете поместить свои частные правила исключения в .git/info/excludeрепозиторий.

Если вы хотите применить одни и те же правила исключения ко всем репозиториям на вашем компьютере, вы можете добавить следующее в .gitconfigфайл в вашем каталоге пользователя.

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

Затем добавьте свои шаблоны исключения в ~/.gitexclude.

Джесси Хоган
источник
1

Возможно, вас заинтересует ловушка обновления, которую написал Юнио и которую Карл улучшил. Поместите приведенный ниже код $GIT_DIR/hooks/updateи не забудьте включить его с помощью 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"

После этого вы даете определенным пользователям или группам возможность вносить изменения в репозиторий. Все, кто может его видеть, имеют доступ только для чтения.

Здесь используются два файла, $GIT_DIR/info/allowed-usersи allowed-groups, чтобы описать, в какие головы и кем можно вставлять. Формат каждого файла будет выглядеть так:

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

При этом Линус может нажимать или создавать bw/penguinor bw/zebraили bw/pandaветки, Паски может делать только cogito, а JC может делать masterи puветки и создавать теги с поддержкой версий. А tmp/blahветки делать может кто угодно . Знак «+» на puзаписи означает, что JC может выполнять на ней нажатие без перемотки вперед.

Если у этого человека еще нет доступа к хосту, на котором находится ваш репозиторий, возможно, у этого человека должен быть только git-shellдоступ, а не неограниченный доступ. Создайте специального пользователя git и в~git/.ssh/authorized_keys добавьте SSH-ключ постороннего в следующую форму. Обратите внимание, что ключ должен быть в одной длинной строке, но я заключил его ниже, чтобы облегчить представление.

no-agent-forwarding, no-port-forwarding, no-pty, no-X11-forwarding,
команда = "env myorg_git_user = joeuser / usr / local / bin / git-shell -c
\ "$ {SSH_ORIGINAL_COMMAND: -} \" "ssh-rsa AAAAB3 ... 2iQ == joeuser@foo.invalid

В зависимости от вашей локальной настройки вам может потребоваться изменить путь к файлу git-shell. Помните, что sshdочень параноидально относится к разрешениям.ssh каталога, поэтому отключите его биты групповой записи и все файлы под ним.

Включение всех пользователей через пользователя git означает, что вы должны уметь различать людей, и это цель myorg_git_userпеременной среды. Вместо того, чтобы полагаться на безусловный username=$(id -u -n), настройте ловушку обновления, чтобы использовать ее:

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

При такой настройке ваш друг с доступом только для чтения будет клонировать с помощью команды, подобной приведенной ниже. Конкретный путь будет зависеть от ваших настроек. Чтобы хороший путь заработал, либо переместите свой репозиторий в домашний каталог пользователя git, либо создайте символическую ссылку, указывающую на него.

$ git clone git@blankman.com.invalid: coolproject.git

но не сможет делать обновления.

$ git push origin mybranch 
Всего 0 (дельта 0), повторно используется 0 (дельта 0)
удаленный: ошибка: хук отказался обновлять ссылки / головы / mybranch
На git@blankman.com.invalid: coolproject.git
 ! [удаленное отклонение] mybranch -> mybranch (крючок отклонен)
ошибка: не удалось отправить некоторые ссылки на 'git@blankman.com.invalid: coolproject.git'

Вы сказали, что работаете в командной среде, поэтому я предполагаю, что ваш центральный репозиторий был создан с этой --sharedопцией. (См core.sharedRepositoryв git configдокументации и --sharedв git initдокументации .) Убедитесь , что новый пользователь мерзавца является членом группы систем , которая дает всем вам доступ к вашему центральному хранилищу.

Грег Бэкон
источник