Ответ 1
Похоже, вы хотите ограничить доступ на чтение для каждого каталога. Это возможно, но единственное решение, о котором я знаю, далеко не просто. Он включает несколько версий одного и того же репозитория на вашем сервере, каждый из которых хранится в синхронизации, используя сложную магию крюка, чтобы отфильтровывать подкаталоги.
Я работаю над реализацией перехватов в свободное время с конечной целью публикации их в качестве программного обеспечения с открытым исходным кодом (возможно, как дополнение к гитолите), но, к сожалению, мое свободное время ограничено.
Хранилища
Общее решение включает в себя как минимум три варианта одного и того же репозитория: один репозиторий полномочий, который координирует два или более репозитория делегатов. Пользователи никогда не клонируют репозиторий полномочий; клонируются только делегированные репозитории.
Делегаты несут ответственность за пересылку входящих коммитов в репозиторий полномочий. Репозиторий полномочий отвечает за фильтрацию входящих коммитов для каждого другого репозитория делегатов. Затем результаты передаются другим делегатам.
Репозиторий полномочий строго не требуется — делегаты могут выполнять фильтрацию самостоятельно, а затем напрямую передавать результаты другим делегатам &mdash, но использование другого репозитория в качестве централизованного координатора значительно упрощает реализацию.
Хранилища делегатов
Каждый репозиторий делегатов содержит подмножество всех данных проекта (например, отфильтрован ноль или более подкаталогов). Все репозитории делегатов идентичны друг другу, за исключением того, что у каждого делегата есть другой набор файлов, отфильтрованных. Все они имеют один и тот же график истории фиксации, но коммиты будут иметь различное содержимое файла и, следовательно, разные идентификаторы 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 из-за того, что содержимое файла отличается.
(Боковое примечание: коммиты также могут быть отфильтрованы, чтобы пользователи другого делегата даже не знали, что сделана фиксация в отфильтрованном каталоге. Однако фиксация может быть отфильтрована только в том случае, если она касается только файлов в отфильтрованный каталог. В противном случае будут конфликты слияния, которые невозможно было бы автоматически разрешить с помощью перехватчиков.)
Репозиторий полномочий
Репозиторий полномочий - это надмножество всех полномочий делегатов. Все объекты фиксации в каждом репозитории делегатов автоматически помещаются в репозиторий полномочий через крючок в каждом репозитории делегатов. Таким образом, если есть два репозитория-делегата, в репозитории полномочий будут два изоморфных группы DAG (по одному от каждого делегата) (при условии, что делегаты не имеют общего корневого коммита).
У репозитория полномочий также будет версия каждой ветки проекта из каждого делегата с префиксом имени делегата. Продолжая приведенный выше пример, репозиторий делегатов everything.git
имеет ветвь master
, указывающую на commit 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
hook:
- Проверяет, пытается ли пользователь создать файл в одном из отфильтрованных каталогов. Если это так, он выходит с ошибкой (в противном случае могут возникнуть конфликты слияния, которые не могут быть разрешены автоматически).
- Возвращает обратно в подкаталоги, которые были первоначально отфильтрованы, чтобы сформировать дерево, которое не отфильтровано.
- Для каждого другого делегата отфильтруйте нефильтрованное дерево, чтобы сделать эквивалентную фиксацию с удаленным содержимым.
- Нажмите эквивалентную фиксацию в репозитории делегатов.
Необходимо соблюдать осторожность, чтобы избежать условий гонки между репозиториями делегатов и правильно обрабатывать ошибки.
Ваш случай
В вашем примере у вас есть два репозитория-делегата, например:
-
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
, чтобы указать на новую фиксацию.
- Создайте новый древовидный объект, который на 100% идентичен дереву фиксации, но удалит все за пределами подкаталогов
- Нажмите
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
.
Примечания
Вышеописанный способ реализации управления доступом к каждому каталогу. Это должно быть удобно, если вы действительно не хотите, чтобы определенные пользователи могли получить доступ к частям репозитория. В вашем случае удобство для вашего дизайнера может быть более важным, чем ограничение доступа. Если это так, может быть более простой способ выполнить то, что вы хотите.
Надеюсь, я смог объяснить это достаточно ясно.