Ответ 1
- Поставьте свои частные правила игнорирования в
.git/info/exclude
. См.gitignore(5)
. - Для доступа только для чтения используйте
git-daemon
, веб-сервер или Gitosis, или Gitolite.
Я работаю в командной среде, и уже есть файл .gitignore
.
Я хочу добавить больше элементов в файл .gitignore
, но я не хочу также проверять этот файл. Можно установить пользовательские файлы игнорирования, которые применимы только ко мне?
Кроме того, я хочу дать кому-то доступ только для чтения к частному репозиторию git на нашем сервере, если я добавлю свой SSH-ключ на наш сервер, они получат полный доступ, как и все остальные. Как я могу ограничить его доступным только для чтения, не разрешено коммит.
.git/info/exclude
. См. gitignore(5)
.git-daemon
, веб-сервер или Gitosis, или Gitolite.Я знаю, что немного опоздал на разговор, но вы можете подумать об использовании
git update-index --assume-unchanged [ FILE ]
Как говорится в справочном документе git:
Когда бит "принять неизменный" включен, git перестает проверять файлы рабочих деревьев на предмет возможных изменений, поэтому вам нужно вручную отключить бит, чтобы сообщить git, когда вы меняете рабочий файл дерева...
Акцент мой. Далее говорится
Этот параметр может быть... использован как механизм грубого файлового уровня для игнорирования незафиксированных изменений в отслеживаемых файлах (сродни тому, что .gitignore делает для невоспроизводимых файлов). git завершится с ошибкой (изящно), если потребуется изменить этот файл в индексе, например. при слиянии в фиксации; таким образом, , в случае, если файл с необработанным неисключенным изменен вверх, вам нужно будет вручную обрабатывать ситуацию.
Поэтому просто имейте в виду, что вам нужно будет знать о любых изменениях, внесенных в эти файлы.
В случае, если вы хотите начать отслеживание файла снова, все, что вам нужно сделать, это использовать
git update-index --no-assume-unchange [ FILE ]
Я надеюсь, что это поможет любым будущим зрителям этого сообщения.
Для части ssh вам следует использовать Gitolite (замена для гитоза).
Как сказал Фред Фродо, вы можете поместить свои частные правила исключения в .git/info/exclude
репозитория.
Если вы хотите применить те же правила исключения ко всем хранилищам на своем компьютере, вы можете добавить следующее в файл .gitconfig
в свой каталог пользователя.
[core]
excludesfile = /home/<myusername>/.gitexclude
Затем добавьте ваши шаблоны исключений в ~/.gitexclude
.
Вам может быть интересен крюк обновления, который написал Джунио и что Карл улучшился. Поместите код ниже в $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 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
При этом Linus может создавать или создавать ветки
bw/penguin
илиbw/zebra
илиbw/panda
, Pasky может выполнять только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, command="env myorg_git_user=joeuser /usr/local/bin/git-shell -c \"${SSH_ORIGINAL_COMMAND:-}\"" ssh-rsa AAAAB3...2iQ== [email protected]
В зависимости от вашей локальной настройки вам может потребоваться настроить путь до 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 [email protected]:coolproject.git
но не сможет делать обновления.
$ 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'
Вы сказали, что работаете в командной среде, поэтому я предполагаю, что ваш центральный репозиторий был создан с помощью опции --shared
. (См. core.sharedRepository
в git config
документации и --shared
в git init
.) Убедитесь, что новый пользователь git является членом системной группы, который дает вам доступ к вашему центральному репозиторию.