Лучшие практики для нескольких репозиториев git

У меня около 20 различных репозиториев. Многие из них независимы и компилируются как библиотеки, но некоторые другие имеют между собой зависимости. Разрешение зависимостей и ветвление сложны.

Предположим, у меня есть суперпроект, который объединяет только все остальные репозитории. Он используется исключительно для запуска тестов — никакой реальной разработки здесь не происходит.

/superproject  [master, HEAD]
    /a         [master, HEAD]
    /b         [master, HEAD]
    /c         [master, HEAD]
    /...

Теперь, чтобы разработать определенные функции или исправления для каждого из них (a), особенно для тех, которые требуют определенных версий проектов для компиляции или запуска (b v2.0 и c 3.0), я должен создать новую ветку:

/superproject  [branch-a, HEAD]  <-- branch for 'a' project
    /a         [master]  <-- new commits here
    /b         [v2.0]
    /c         [v3.0]

Для b может потребоваться что-то еще, например a v0.9 и c v3.1:

/superproject  [branch-b, HEAD]  <-- branch for 'b' project
    /a         [v0.9]   <-- older version than 'a'
    /b         [master] <-- new commits go here
    /c         [v3.1]   <-- newer version than 'a'

Это становится еще более сложным и сложным при реализации общих рабочих процессов git, включающих ветки функций, ветки исправлений, ветки выпуска и т. д. Мне советовали (и не советовали) использовать git-submodules, git-subtree, git-repo, git-slave Google и т. д.

Как я могу управлять непрерывной интеграцией для такого сложного проекта?

ИЗМЕНИТЬ

Реальный вопрос заключается в том, как запускать тесты без необходимости имитировать все другие зависимые проекты? Особенно, когда все проекты могут использовать разные версии. Запуск тестов Jenkins после фиксации в подмодулях git


person betodelrio    schedule 03.07.2015    source источник
comment
Я бы на самом деле обескуражил такую ​​архитектуру. Наличие такого репозитория только запутает сопровождающих, а тестирование действительно должно проводиться для каждого проекта.   -  person Makoto    schedule 03.07.2015
comment
Отдельные папки выше представляют собой разные репозитории .git, а не один большой, иначе они не могли бы иметь разные ветки и теги.   -  person AlBlue    schedule 03.07.2015
comment
Реальный вопрос заключается в том, как запускать тесты без необходимости имитировать все другие зависимые проекты? Особенно, когда все проекты могут использовать разные версии.   -  person betodelrio    schedule 03.07.2015


Ответы (2)


Для параллельной работы с несколькими ветвями используйте параллельные клоны, если это возможно. cd намного проще, чем извлечение и очистка, проверка устаревшего мусора и воссоздание кеша каждый раз, когда вы хотите переключиться.


Что касается записи ваших тестовых сред, вы описываете именно то, что делают субмодули, во всех деталях. Для чего-то такого простого я собираюсь порекомендовать настроить себя без использования команды submodule вообще и сообщить ей о своей настройке, как только вы почувствуете себя комфортно, а верхний элемент в вашем списке проблем с подмодулем — это количество нажатий клавиш.

Начиная с настройки в вашем вопросе, вот как вы настраиваете себя на запись чистых сборок в подпроектах:

cd $superproject
git init .
git add a b c etc
git commit -m "recording test state for $thistest"

Вот и все. Вы зафиксировали список идентификаторов коммитов, то есть идентификаторов проверенных в данный момент коммитов в каждом из этих репозиториев. Фактический контент находится в этих репозиториях, а не в этом, но в этом вся разница между файлами и подмодулями с точки зрения git. В файле .gitmodules есть случайные примечания в помощь клонерам, в основном предлагаемый репозиторий, который должен содержать необходимые коммиты, и случайные примечания для команд по умолчанию, но то, что он делает, просто и очевидно.

Хотите проверить правильный коммит по пути foo?

(commit=`git rev-parse :foo`; cd foo; git checkout $commit)

rev-parse извлекает идентификатор контента для foo из индекса, cd и checkout делают это.

Вот как вы находите все свои подмодули и что там нужно проверить, чтобы воссоздать поэтапную индексированную среду:

git ls-files -s | grep ^16

Проверьте, что указано в вашем текущем индексе для подмодуля и что там действительно проверено:

echo $(git rev-parse :$submodule; (cd $submodule; git rev-parse HEAD))

и вот вы идете. Проверить правильные коммиты во всех ваших подмодулях?

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd "$path"; git checkout $commit)
done

Иногда у вас есть локальные патчи, которые вы хотите применять к каждой кассе:

git ls-files -s | grep ^16 | while read mode commit stage path; do
        (cd $path; git rebase $commit)
done

и так далее. Для них есть git submodule команд, но они не делают ничего, чего вы не видели выше. То же самое и для всех остальных, вы можете перевести все, что они делают, в почти однострочные, такие как приведенные выше.

В подмодулях нет ничего загадочного.


Непрерывная интеграция обычно выполняется с помощью любого из множества инструментов, я оставлю это для кого-то еще обратиться.

person jthill    schedule 03.07.2015
comment
Отличный ответ. Как отслеживать зависимости версий, не возвращаясь к подмодулям superproject? Проект a требует b определенной версии. Могу ли я установить это ограничение как часть самого a? - person betodelrio; 06.07.2015
comment
А, хорошо, я отвожу своего ребенка в лагерь и немного поторопился с предыдущим комментарием. Да, вы можете сделать свои зависимости таким образом — для этого нет гаджета подмодуля, но опять же это почти однострочник — чтобы добавить подмодуль, который фактически находится в другом месте, вы идете в другое место и говорите git config worktree .., чтобы зафиксировать расположение рабочего дерева. и в рабочих деревьях, использующих его, а не ваше первоначальное обновление подмодуля, вы делаете echo gitdir: /path/to/projecta/.git >$theprojectbpath_in_a. Поиграйте с этим, завтра у меня будет больше времени. - person jthill; 06.07.2015

Как автор, git slave мог бы работать в этой ситуации. Как его использовать, будет зависеть от того, есть ли у вас контроль над репозиториями a b и c; под этим я подразумеваю, что вы можете синхронизировать стратегию ветвления между ними, чтобы ветвь v2 означала одно и то же для всех. Если это правда, я настоятельно рекомендую git slave, так как вы можете рассматривать это как один большой проект.

Если бы вы не могли предписать общую стратегию ветвей и тегов, вы бы навязали одну, которая больше приближается к облегченной версии рабочего процесса, которую jthill предложил с git submodules. В частности, вы можете иметь свое собственное отслеживание репо a b и c и создать ветку branch a в каждой из них, которая будет соответствовать любым правильным ветвям для каждого ведомого репо. Как и в случае с git submodules, вам придется вручную обновлять каждое репо (в данном случае - слияние). Тем не менее, вам не нужно делать шаг матери, могу ли я сделать фиксацию в суперпроекте. Использование этого метода не является беспроигрышным случаем, когда подчиненные проекты используют одно и то же имя ветки, когда они выполняют свою собственную разработку, но это сработает.

Как сказал Джейтхилл, непрерывная интеграция в значительной степени несовместима с вопросом о том, как урегулировать проекты.

person Seth Robertson    schedule 04.07.2015
comment
Нет, я не могу указать общую ветку/тег в подмодулях (ведомых репозиториях). gits кажется более сложным, чем то, чего я пытаюсь достичь, но попробую. Спасибо :D - person betodelrio; 06.07.2015