2011-05-24 145 views
60

我在团队环境中工作,并且已经有一个.gitignore文件。是否有可能有一个自定义.gitignore?只读访问?

我想添加更多的项目到.gitignore文件,但我不想检查这个文件。可以设置只适用于我的自定义忽略文件吗?如果我们将SSH密钥添加到我们的服务器,他们将像其他人一样获得完全访问权限。我怎样才能将其限制为只读,不允许提交。

+0

可能重复[我可以创建一个特定于用户的gitignore文件吗?](https://stackoverflow.com/questions/5724455/can-i-make-a-user-specific-gitignore-file) – 2017-11-07 15:31:57

回答

91
  1. 把你的私人忽略规则放在.git/info/exclude。见gitignore(5)
  2. 对于只读访问,请使用git-daemonweb server或Gitosis或Gitolite。
+0

并使情况更糟糕,我想这个gitignore是为一个特定的项目,而不是全局设置。 – Blankman 2011-05-24 21:44:21

+7

@Blankman:将它放在项目根目录下的'.git/info/exclude' *中*。 – 2011-05-24 21:45:15

+1

使其完成:使用配置选项'core.excludesfile',您可以指定_global_排除文件。 – KingCrunch 2011-05-24 21:47:04

2

对于ssh部分,您应该考虑使用Gitolite(替代gitosis)。

0

你可能会对Junio写的update hook感兴趣,并且Carl改进了。将下面的代码放在$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分支机构,Pasky能做的只有​​,和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== [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 documentation--shared,git init documentation。)确保新的git用户是系统组的成员,它为您提供了所有对中央存储库的访问权限。

15

我知道我有点晚了交谈,但你可能要考虑使用

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

由于git的帮助文件规定:

当“假设不变”位上,git停止检查工作树文件的可能的修改,所以你需要手动取消设置该位,告诉GIT当你改变工作树文件...

强调我的。它接着说

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

所以,请记住,您将不得不意识到对这些文件所做的任何上游更改。

在要开始跟踪该文件的事件再次所有你需要做的就是使用

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

我希望这可以帮助任何未来的这个帖子的观众。

0

就像Fred Frodo说的那样,您可以将您的私人排除规则放入存储库的.git/info/exclude中。

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

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

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

相关问题