ディレクトリごとに読み取りアクセスを制限できるようにしたいようです。これは可能ですが、私が知っている唯一の解決策は単純ではありません。これには、サーバー上の同じリポジトリの複数のバージョンが含まれ、それぞれが複雑なフックマジックを使用して同期を維持し、サブディレクトリを除外します。
フックをオープンソースソフトウェアとして(おそらくgitoliteの機能追加として)公開することを最終的な目標として、空き時間にフックの実装に取り組んでいますが、残念ながら空き時間は限られています。
リポジトリ
一般的なソリューションには、同じリポジトリの少なくとも3つのバリアントが含まれます。2つ以上のデリゲートリポジトリを調整する1つの権限リポジトリ。ユーザーが権限リポジトリのクローンを作成することはありません。デリゲートリポジトリのみが複製されます。
デリゲートは、着信コミットを権限リポジトリに転送する責任があります。権限リポジトリは、他のデリゲートリポジトリごとに着信コミットを適切にフィルタリングする責任があります。その後、結果は他の代表者にプッシュダウンされます。
権限リポジトリは厳密には必要ありません。デリゲートは独自にフィルタリングを実行し、結果を他のデリゲートに直接プッシュできますが、集中コーディネーターとして別のリポジトリを使用すると、実装が大幅に簡素化されます。
リポジトリの委任
各デリゲートリポジトリには、プロジェクト全体のデータのサブセットが含まれています(たとえば、ゼロ個以上のサブディレクトリが除外されます)。すべてのデリゲートリポジトリは、各デリゲートに異なるファイルのセットが除外されていることを除いて、互いに同一です。それらはすべて同じコミット履歴グラフを持っていますが、コミットは異なるファイルの内容を持ち、したがって異なるSHA1識別子を持ちます。それらには同じブランチとタグのセットがあります(つまり、プロジェクトにmaster
ブランチがある場合、各デリゲートリポジトリにもmaster
ブランチがあります)が、同等のコミットのSHA1識別子が異なるため、参照は異なるSHA1を指します。識別子。
たとえば、以下は2つのデリゲートリポジトリのコンテンツのグラフです。everything.git
リポジトリには何も除外されていませんが、リポジトリno-foo.git
にはサブディレクトリ内のすべてがfoo
除外されています。
$ cd ~git/repositories/everything.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (HEAD, master) barbaz
| * c3eb6a9 (release) foobar
* | 8b56913 Merge branch 'release'
|\ \
| |/
| * b8f899c qux
* | aad30f1 baz
|/
* f4acd9f put a new file in subdirectory bar
* 2a15586 put a new file in subdirectory foo
$ cd ~git/repositories/no-foo.git
$ git log --graph --oneline --decorate --date-order --all
* 81c2189 (HEAD, master) barbaz
| * 6bbd85f (release) foobar
* | c579c4b Merge branch 'release'
|\ \
| |/
| * 42c45c7 qux
* | 90ecdc7 baz
|/
* 4d1cd8d put a new file in subdirectory bar
* 9cc719d put a new file in subdirectory foo
2つのグラフは同じように見え、同じコミットメッセージ、同じブランチ名などを持っていることに注意してください。唯一の違いは、ファイルの内容が異なるため、SHA1IDです。
(補足:コミットもフィルターで除外して、別のデリゲートのユーザーがフィルターで除外されたディレクトリでコミットが行われたことを知らないようにすることができます。ただし、コミットは、フィルターで除外されたディレクトリ内のファイルにのみアクセスする場合にのみフィルターで除外できます。アウトディレクトリ。そうしないと、フックによって自動的に解決できないマージの競合が発生します。)
権限リポジトリ
権限リポジトリは、すべての委任権限のスーパーセットです。各デリゲートリポジトリ内のすべてのコミットオブジェクトは、各デリゲートリポジトリ内のフックを介して権限リポジトリに自動的にプッシュされます。したがって、2つのデリゲートリポジトリがある場合、権限リポジトリに2つの同形DAG(各デリゲートから1つ)があります(デリゲートが共通のルートコミットを共有しないと想定)。
権限リポジトリには、各デリゲートからの各プロジェクトブランチのバージョンがあり、その前にデリゲートの名前が付いています。上記の例を続けると、everything.git
デリゲートリポジトリにはmaster
コミットを指すブランチがあり、2faaad9
デリゲートにはフィルタリングされているがそれ以外の場合は同等のコミットを指すブランチがあります。このシナリオでは、を指すとを指すという2つのマスターブランチが あります。次のグラフはこれを示しています。no-foo.git
master
81c2189
authority.git
everything/master
2faaad9
no-foo/master
81c2189
$ cd ~git/repositories/authority.git
$ git log --graph --oneline --decorate --date-order --all
* 2faaad9 (everything/master) barbaz
| * 81c2189 (no-foo/master) barbaz
| | * c3eb6a9 (everything/release) foobar
| | | * 6bbd85f (no-foo/release) foobar
* | | | 8b56913 Merge branch 'release'
|\ \ \ \
| | |/ /
| |/| |
| | * | c579c4b Merge branch 'release'
| | |\ \
| | | |/
| * | | b8f899c qux
| | | * 42c45c7 qux
* | | | aad30f1 baz
|/ / /
| * | 90ecdc7 baz
| |/
* | f4acd9f put a new file in subdirectory bar
| * 4d1cd8d put a new file in subdirectory bar
* | 2a15586 put a new file in subdirectory foo
/
* 9cc719d put a new file in subdirectory foo
各コミットには2つのバージョンがあり、各デリゲートに1つずつあることに注意してください。ブランチ名にも注意してください。
フック
リポジトリの委任
各デリゲートは、権限リポジトリへのコミットをフィードします。
ユーザーがデリゲートリポジトリ内の参照を(経由でgit push
)更新すると、そのリポジトリのupdate
フックが自動的git push
に権限リポジトリにアクセスします。ただし、標準のプッシュrefspecを使用する代わりに、機関のリポジトリ内の参照の前にデリゲートリポジトリの名前を付けるrefspecを使用します(たとえば、デリゲートリポジトリに名前が付けられている場合は、andfoo.git
のようなプッシュrefspecを使用します)。+refs/heads/master:refs/heads/foo/master
+refs/tags/v1.0:refs/tags/foo/v1.0
権限リポジトリ
権限リポジトリは、着信コミットをフィルタリングし、それらを他のデリゲートリポジトリにプッシュダウンします。
デリゲートリポジトリが権限リポジトリにプッシュすると、権限のupdate
フックは次のようになります。
- ユーザーがフィルターで除外されたディレクトリの1つにファイルを作成しようとしているかどうかを確認します。その場合、エラーで終了します(そうでない場合、自動的に解決できないマージの競合が発生する可能性があります)。
- 元々フィルターで除外されていたサブディレクトリに移植して、何もフィルターで除外されていないツリーを形成します。
- 他のデリゲートごとに、フィルタリングされていないツリーをフィルタリングして、適切なコンテンツを削除して同等のコミットを行います。
- 同等のコミットをデリゲートリポジトリにプッシュします。
デリゲートリポジトリ間の競合状態を回避し、エラーを適切に処理するように注意する必要があります。
あなたの場合
あなたの例では、次のような2つのデリゲートリポジトリがあります。
everything.git
(あなたのために)
zend-project.git
(あなたのデザイナーのために)
のブランチにauthority.git
は、プレフィックスが付けられ、2つのデリゲートリポジトリに対応しますeverything
。zend-project
にプッシュするmaster
とeverything.git
、次のようになります。
- フックイン
update
はeverything.git
、着信コミットをのeverything/master
ブランチにプッシュしauthority.git
ます。
- 着信コミットごとに、
update
フックインは次のようにauthority.git
なります。
application
コミットのツリーと100%同一であるが、およびサブディレクトリの外側のすべてを削除する新しいツリーオブジェクトを作成しますpublic
。
- 新しいツリーと同等の親を使用して新しいコミットオブジェクトを作成しますが、元のコミットメッセージ、作成者、およびタイムスタンプを再利用します。
zend-project/master
新しいコミットを指すように更新します。
- に押し込みます。
zend-project/master
_authority.git
master
zend-project.git
デザイナーがプッシュmaster
インするzend-project.git
と、次のようになります。
- フックイン
update
はzend-project.git
、着信コミットをのzend-project/master
ブランチにプッシュしauthority.git
ます。
- 着信コミットごとに、
update
フックインは次のようにauthority.git
なります。
application
またはサブディレクトリの外部に新しいファイルが作成されていないかどうかを確認してくださいpublic
。その場合は、エラーメッセージを表示して戻ります。
everything/master
に移植された他のサブディレクトリを除いて、コミットのツリーと100%同一の新しいツリーオブジェクトを作成します。
- 新しいツリーと同等の親を使用して新しいコミットオブジェクトを作成しますが、元のコミットメッセージ、作成者、およびタイムスタンプを再利用します。
everything/master
新しいコミットを指すように更新します。
- に押し込みます。
everything/master
_authority.git
master
everything.git
ノート
上記は、ディレクトリごとの読み取りアクセス制御を実装する方法を説明しています。特定のユーザーがリポジトリの一部にアクセスできないようにする場合に適しています。あなたの場合、アクセスを制限するよりも、設計者の利便性の方が重要な場合があります。もしそうなら、あなたが望むことを達成するためのより簡単な方法があるかもしれません。
これを十分に明確に説明できたと思います。