Звучит так, будто вы хотите иметь возможность ограничивать доступ на чтение для каждого каталога.Это возможно, но единственное известное мне решение далеко не простое.Он включает в себя несколько версий одного и того же репозитория на вашем сервере, каждая из которых синхронизируется с использованием некоторой сложной магии ловушек для фильтрации подкаталогов.
В свободное время я работаю над реализацией ловушек с возможной целью:публикуя их как программное обеспечение с открытым исходным кодом (возможно, как дополнение к gitolite), но, к сожалению, мое свободное время ограничено.
Репозитории
Общее решение включает как минимум три варианта одного и того же репозитория:Один авторитетный репозиторий, который координирует два или более делегата репозиториев.Пользователи никогда не клонируют хранилище полномочий;клонируются только репозитории делегатов.
Делегаты отвечают за пересылку входящих коммитов в репозиторий полномочий.Хранилище полномочий отвечает за надлежащую фильтрацию входящих коммитов для каждого репозитория делегатов.Затем результаты передаются другим делегатам.
Репозиторий полномочий строго не требуется - делегаты могут выполнять фильтрацию самостоятельно, а затем передавать результаты непосредственно другим делегатам, но используя другой репозиторий какцентрализованный координатор значительно упрощает реализацию.
Репозитории делегатов
Каждый репозиторий делегатов содержит подмножество данных всего проекта (например, отфильтровано ноль или более подкаталогов).Все репозитории делегатов идентичны друг другу, за исключением того, что каждый делегат имеет свой набор отфильтрованных файлов.Все они имеют один и тот же граф истории коммитов, но коммиты будут иметь разное содержимое файла и, следовательно, разные идентификаторы SHA1.Они имеют одинаковый набор ветвей и тегов (другими словами, если у проекта есть ветвь master
, то в каждом репозитории делегатов также есть ветвь master
), но поскольку идентификаторы SHA1 для эквивалентных коммитов различны,ссылки будут указывать на разные идентификаторы SHA1.
Например, ниже приведены графики содержимого двух репозиториев делегатов.В репозитории 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
Обратите внимание, что два графика выглядят одинаково, имеют одинаковыйфиксировать сообщения, одни и те же имена веток и т. д. Единственное отличие - это идентификаторы SHA1 из-за различий в содержимом файла.
(Примечание: коммиты также могут быть отфильтрованы, чтобы не допустить пользователей другогоделегат даже не знает, что был сделан коммит в отфильтрованном каталоге. Однако, коммит можно отфильтровать, только если он касается только файлов в отфильтрованном каталоге. В противном случае могут возникнуть конфликты слияния, которые не могут быть разрешены автоматическивсеми правдами и неправдами.)
Хранилище полномочий
Хранилище полномочий - это расширенный набор всех полномочий делегатов.Все объекты коммитов в каждом репозитории делегатов автоматически помещаются в репозиторий полномочий через хук в каждом репозитории делегатов.Таким образом, если есть два репозитория делегатов, в репозитории полномочий будут две изоморфные группы обеспечения доступности баз данных (по одному от каждого делегата) (при условии, что у делегатов нет общего корневого коммита).
Репозиторий полномочий также будетиметь версию каждой ветви проекта от каждого делегата с префиксом имени делегата.Продолжая приведенный выше пример, репозиторий делегатов everything.git
имеет ветку master
, указывающую на фиксацию 2faaad9
, а делегат 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
Обратите внимание, что существует две версии каждого коммита, по одному для каждого делегата. Также обратите внимание на названия филиалов.
Крючки
Репозитории делегатов
Каждый фид делегата фиксирует в хранилище полномочий.
Когда пользователь обновляет ссылку (через git push
) в репозитории делегатов, хук update
этого репозитория автоматически делает git push
в репозитории полномочий. Однако вместо использования стандартного push-refspec он использует refspec, в результате чего ссылка в репозитории органа префиксируется именем репозитория делегата (например, если репозиторий делегата имеет имя foo.git
, тогда он будет использовать push refspecs, например +refs/heads/master:refs/heads/foo/master
и +refs/tags/v1.0:refs/tags/foo/v1.0
).
Хранилище полномочий
Хранилище полномочий фильтрует входящие коммиты и помещает их в другие репозитории делегатов.
Когда репозиторий делегатов помещается в репозиторий полномочий, перехват update
полномочий:
- Проверяет, пытается ли пользователь создать файл в одном из отфильтрованных каталогов. Если это так, он завершается с ошибкой (в противном случае могут возникнуть конфликты слияния, которые не могут быть разрешены автоматически).
- Возвращает обратно в подкаталоги, которые изначально были отфильтрованы, с образованием дерева, в котором ничего не отфильтровано.
- Для каждого другого делегата отфильтруйте нефильтрованное дерево, чтобы сделать эквивалентный коммит с соответствующим удаленным содержимым.
- Нажмите эквивалентные коммиты в репозитории делегатов.
Необходимо соблюдать осторожность, чтобы избежать расы между репозиториями делегатов и правильно обрабатывать ошибки.
Ваш случай
В вашем примере у вас будет два репозитория делегатов, подобных этому:
everything.git
(для вас)
zend-project.git
(для вашего дизайнера)
Ветвям в authority.git
будет предшествовать everything
и zend-project
, соответствующие двум репозиториям делегатов.
Когда вы нажимаете master
в everything.git
, происходит следующее:
- Хук
update
в everything.git
будет толкать входящие коммиты в ветку everything/master
в authority.git
.
- Для каждой входящей фиксации хук
update
в authority.git
будет:
- Создайте новый объект дерева, который на 100% идентичен дереву коммита, но удалите все, что находится вне подкаталогов
application
и 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
. Если это так, вернитесь с сообщением об ошибке.
- Создайте новый объект дерева, который на 100% идентичен дереву коммита, за исключением того, что в него вложены другие подкаталоги из
everything/master
.
- Создайте новый объект фиксации, используя новое дерево и эквивалентные родительские элементы, но повторно используйте исходное сообщение фиксации, автора и метку времени.
- Обновление
everything/master
для указания нового коммита.
- Нажмите
everything/master
в authority.git
до master
в everything.git
.
Примечания
Выше описан способ реализации контроля доступа на чтение для каждого каталога. Это должно подойти, если вы действительно не хотите, чтобы определенные пользователи имели доступ к частям репозитория. В вашем случае удобство для вашего дизайнера может быть важнее, чем ограничение доступа. Если это так, может быть более простой способ выполнить то, что вы хотите.
Я надеюсь, что смог объяснить это достаточно ясно.