web-dev-qa-db-ja.com

カスタム.gitignoreを持つことは可能ですか?読み取り専用アクセス?

私はチーム環境で作業しており、すでに.gitignoreファイルがあります。

.gitignoreファイルにアイテムを追加したいのですが、このファイルもチェックインしたくありません。私だけに適用されるカスタム無視ファイルを設定することは可能ですか?

また、サーバーにプライベートgitリポジトリへの読み取り専用アクセスを付与したいのですが、SSHキーをサーバーに追加すると、他の人と同じようにフルアクセスを取得できます。コミットを許可せずに、読み取り専用に制限するにはどうすればよいですか。

74
Blankman
  1. プライベートな無視ルールを_.git/info/exclude_に入れます。 gitignore(5) を参照してください。
  2. 読み取り専用アクセスの場合は、 _git-daemon_Webサーバー 、またはGitosis、またはGitoliteを使用します。
112
Fred Foo

私は会話に少し遅れていることを知っていますが、あなたは使用を検討したいかもしれません

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

Git help documentが述べているように:

「変更されていない」ビットがオンの場合、gitは作業ツリーファイルの変更のチェックを停止しますなので、作業ツリーファイルを変更したときにgitに通知するには、ビットの設定を手動で解除する必要があります...

鉱山を強調します。それは言い続ける

このオプションは... 追跡されたファイルでコミットされていない変更を無視するための大まかなファイルレベルのメカニズムとして使用されます(追跡されていないファイルに対して.gitignoreが行うことと同様)。インデックスでこのファイルを変更する必要がある場合、Gitは(正常に)失敗します。コミットをマージするとき;したがって、想定された追跡されていないファイルが上流で変更された場合、手動で状況を処理する必要があります

したがって、これらのファイルに加えられた上流の変更に注意する必要があることを覚えておいてください。

もう一度ファイルの追跡を開始したい場合は、使用するだけです

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

これがこの投稿の将来の視聴者の皆さんに役立つことを願っています。

18
Jake Greene

Sshの部分については、 Gitolite (gitosisの代替)の使用を検討する必要があります。

2
Simon

Fred Frodoが言ったように、プライベートな除外ルールをリポジトリの.git/info/excludeに置くことができます。

マシン上のすべてのリポジトリに同じ除外ルールを適用する場合は、ユーザーディレクトリの.gitconfigファイルに以下を追加できます。

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

次に、除外パターンを~/.gitexcludeに追加します。

1
Jesse Hogan

Junioが作成し、Carlが改善した updateフック に興味があるかもしれません。以下のコードを$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の2つのファイルを使用して、誰がどのヘッドにプッシュできるかを記述します。各ファイルの形式は次のようになります。

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キーを追加します。キーは長い1行に収める必要があることに注意してください。ただし、わかりやすくするために、以下で囲みました。

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

この設定を使用すると、読み取り専用アクセス権を持つ友達は、次のようなコマンドでクローンを作成します。特定のパスは、セットアップによって異なります。 Niceパスを機能させるには、リポジトリをgitユーザーのホームディレクトリに再配置するか、それを指すシンボリックリンクを作成します。

$ git clone [email protected]:coolproject.git

ただし、更新を行うことはできません。

$ git Push Origin mybranch 
合計0(デルタ0)、再利用0(デルタ0)
リモート:エラー:フックが拒否され、refs/heads/mybranch 
 To git @ blankmanに更新されました.com.invalid:coolproject.git 
! [リモートで拒否されました] mybranch-> mybranch(フックが拒否されました)
エラー:一部の参照を '[email protected]:coolproject.git'にプッシュできませんでした

チーム環境で作業しているとのことですが、中央リポジトリは--sharedオプションで作成されたと思います。 ( core.sharedRepositoryドキュメントgit configおよび --sharedドキュメントgit initを参照してください。)新しいgitユーザーが、中央リポジトリへのアクセス権をすべて付与するシステムグループのメンバーであることを確認してください。

0
Greg Bacon