git 是否可以自定义 .gitignore?只读权限?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6117109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 05:31:13  来源:igfitidea点击:

Is it possible to have a custom .gitignore? Read only access?

gitgitignore

提问by Blankman

I am working in a team environment, and there is already a .gitignorefile.

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

I want to add more items to the .gitignorefile, but I don't want to check this file in either. It is possible to set custom ignore files which only apply to me?

我想向.gitignore文件中添加更多项目,但我也不想检查此文件。可以设置仅适用于我的自定义忽略文件吗?

Also, I want to give someone read only access to a private git repository on our server, if I add their SSH key to our server they will get full access like everyone else. How can I limit it to read-only, no commits allowed.

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

回答by Fred Foo

  1. Put your private ignore rules in .git/info/exclude. See gitignore(5).
  2. For read-only access, use git-daemon, a web server, or Gitosis, or Gitolite.
  1. 将您的私人忽略规则放在.git/info/exclude. 见gitignore(5)
  2. 对于只读访问,使用git-daemon,一个web服务器,或者Gitosis的,或Gitolite。

回答by Jake Greene

I know I am a little late to the conversation but you might want to consider using

我知道我的谈话有点晚了,但你可能想考虑使用

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

As the git help document states:

正如 git 帮助文档所述:

When the "assume unchanged" bit is on, git stops checking the working tree files for possible modifications, so you need to manually unset the bit to tell git when you change the working tree file...

当“假设未更改”位打开时,git 停止检查工作树文件以进行可能的修改,因此您需要手动取消设置该位以告诉 git 何时更改工作树文件...

Emphasis mine. It goes on to say

强调我的。它接着说

This option can be ... used as a coarse file-level mechanism to ignore uncommitted changes in tracked files(akin to what .gitignore does for untracked files). Git will fail (gracefully) in case it needs to modify this file in the index e.g. when merging in a commit; thus, in case the assumed-untracked file is changed upstream, you will need to handle the situation manually.

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

So just keep in mind that you will have to be aware of any upstream changes made to these files.

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

In the event that you want to start tracking the file again all you have to do is use

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

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

I hope this helps any future viewers of this post.

我希望这对这篇文章的任何未来观众有所帮助。

回答by Jesse Hogan

Like Fred Frodo said, you can put your private exclude rules in the .git/info/excludeof the repository.

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

If you want to apply the same exclude rules to all the repositories on your machine, you can add the following to the .gitconfigfile in your user directory.

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

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

Then add your exclude patterns to ~/.gitexclude.

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

回答by Simon

For the ssh part, you should consider using Gitolite(a replacement for gitosis).

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

回答by Greg Bacon

You may be interested in an update hookthat Junio wrote and that Carl improved. Place the code below in $GIT_DIR/hooks/updateand don't forget to enable it with chmod +x.

您可能对Junio 编写且 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-     "
  echo grant
  exit 0
}

function deny {
  $verbose && echo >&2 "-Deny-      "
  echo deny
  exit 1
}

function info {
  $verbose && echo >&2 "-Info-      "
}

# 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 "" in
  refs/tags/*)
    git rev-parse --verify -q "" &&
    deny >/dev/null "You can't overwrite an existing tag"
    ;;
  refs/heads/*)
    # No rebasing or rewinding
    if expr "" : '0*$' >/dev/null; then
      info "The branch '' is new..."
    else
      # updating -- make sure it is a fast-forward
      mb=$(git-merge-base "" "")
      case "$mb," in
        ",$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 "" : "${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 "" : "${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"

With this hook in place, you then give particular users or groups to make changes to the repository. Anyone else who can see it has read-only access.

有了这个钩子,你就可以让特定的用户或组对存储库进行更改。可以看到它的任何其他人都具有只读访问权限。

This uses two files, $GIT_DIR/info/allowed-usersand allowed-groups, to describe which heads can be pushed into by whom. The format of each file would look like this:

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

With this, Linus can push or create bw/penguinor bw/zebraor bw/pandabranches, Pasky can do only cogito, and JC can do masterand pubranches and make versioned tags. And anybody can do tmp/blahbranches. The '+' sign at the purecord means that JC can make non-fast-forward pushes on it.

这使用两个文件$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

有了这个,Linus 可以推送或创建bw/penguinbw/zebrabw/panda分支,Pasky 只能做cogito,而 JC 可以做masterpu分支并制作版本化标签。任何人都可以做tmp/blah分支。记录上的“+”号pu表示 JC 可以对其进行非快进推动。

If this person doesn't already have access to the host where your repository lives, maybe that person should have only git-shellaccess rather than unrestricted access. Create a special-purpose git user and in ~git/.ssh/authorized_keys, add the outsider's SSH key in the following form. Note that the key should be on one long line, but I've wrapped it below to aid presentation.

如果此人还没有访问您的存储库所在的主机的权限,那么该人可能应该只有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]

Depending on your local setup, you may need to adjust the path to git-shell. Remember that sshdis highly paranoid about permissions of the .sshdirectory, so turn off its group-write bits and all files beneath it.

根据您的本地设置,您可能需要将路径调整为git-shell. 请记住,这sshd是对.ssh目录权限的高度偏执,因此请关闭其组写入位及其下的所有文件。

Funneling everyone through the git user means you need to be able tell people apart, and this is the purpose of the myorg_git_userenvironment variable. Instead of relying on an unconditional username=$(id -u -n), tweak your update hook to use it:

通过 git 用户汇集每个人意味着您需要能够区分人们,这就是myorg_git_user环境变量的目的。与其依赖 unconditional 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'"

With this setup, your friend with readonly access will clone with a command resembling the one below. The particular path will depend on your setup. To make the nice path work, either relocate your repository to the git user's home directory or create a symlink that points to it.

使用此设置,您的具有只读访问权限的朋友将使用类似于以下命令的命令进行克隆。特定路径将取决于您的设置。为了使好的路径起作用,请将您的存储库重新定位到 git 用户的主目录或创建一个指向它的符号链接。

$ git clone [email protected]: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 [email protected]:coolproject.git
 ! [remote rejected] mybranch -> mybranch (hook declined)
error: failed to push some refs to '[email protected]:coolproject.git'

You said you're working in a team environment, so I assume your central repository was created with the --sharedoption. (See core.sharedRepositoryin the git configdocumentationand --sharedin the git initdocumentation.) Make sure the new git user is a member of the system group that gives all of you access to your central repository.

您说您在团队环境中工作,所以我假设您的中央存储库是使用该--shared选项创建的。(见core.sharedRepository的在git config文档--sharedgit init文档。)确保新的git用户,让大家访问你的中央资料库系统组的成员。