有没有可能有一个自定义的。 gitignore? 只读访问?

我在一个团队环境中工作,并且已经有一个 .gitignore文件。

我想添加更多的项目到 .gitignore文件,但我也不想签入这个文件。是否可以设置只适用于我的自定义忽略文件?

此外,我想给某人只读访问我们的服务器上的私有 git 存储库,如果我添加他们的 SSH 密钥到我们的服务器,他们将获得完全访问像其他人一样。如何将其限制为只读,不允许提交。

20683 次浏览
  1. 将您的私人忽略规则放在 .git/info/exclude中。参见 gitignore(5)
  2. 对于只读访问,使用 git-daemon网络伺服器、 Gitosis 或 Gitolite。

对于 ssh 部分,您应该考虑使用 基托石(一种替代 gitosis 的方法)。

你可能对朱尼奥写的 更新钩子和卡尔改进的 更新钩子感兴趣。将下面的代码放在 $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-usersallowed-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/penguinbw/zebrabw/panda分支,帕斯基只能做 cogito,而 JC 可以做 masterpu分支,并制作版本标记。任何人都可以做 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== joeuser@foo.invalid

根据您的本地设置,您可能需要调整路径到 git-shell。请记住,sshd.ssh目录的权限高度偏执,因此请关闭它的组写位和它下面的所有文件。

让每个人都通过 git 用户意味着你需要能够区分不同的人,这就是 abc0环境变量的目的。不要依赖于无条件的 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

but won't be able to make updates.

$ git push origin mybranch
Total 0 (delta 0), reused 0 (delta 0)
remote: error: hook declined to update refs/heads/mybranch
To git@blankman.com.invalid:coolproject.git
! [remote rejected] mybranch -> mybranch (hook declined)
error: failed to push some refs to 'git@blankman.com.invalid:coolproject.git'

您说过您在一个团队环境中工作,所以我假设您的中央存储库是使用 --shared选项创建的。(见 git config文档中的 core.sharedRepositorygit init文档中的 --shared。)确保新的 git 用户是系统组的成员,该系统组允许所有用户访问您的中央存储库。

我知道现在说这个有点晚了但是你可以考虑一下

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

正如 git 帮助文档所述:

Git 停止检查工作树文件是否存在可能的修改启用“假设未更改”位时,需要手动取消该位的设置,以便在更改工作树文件时告诉 git..。

重点是我的,上面还说

这个选项可以是... 用作粗略的文件级机制,以忽略跟踪文件中未提交的更改(类似于。对于未跟踪的文件)。如果需要在索引中修改这个文件,Git 将失败(优雅地) ,例如在提交中合并时; 因此,如果假定未跟踪的文件在上游发生更改,则需要手动处理这种情况

所以请记住,您必须了解对这些文件所做的任何上游更改。

如果您想再次开始跟踪文件,那么只需使用

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

我希望这能帮助任何未来的观众。

正如 Fred Frodo 所说,您可以将您的私有排除规则放在存储库的 .git/info/exclude中。

如果希望对计算机上的所有存储库应用相同的排除规则,可以向用户目录中的 .gitconfig文件添加以下内容。

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

然后将排除模式添加到 ~/.gitexclude