Подтвердить что ты не робот

Git вложенные подмодули и зависимости

Скажем, у меня четыре проекта с именем Core, A, B, Супер. Дерево зависимостей выглядит так:

Super ---> Core
       |-> A -> Core
       |-> B -> Core

Я хочу, чтобы каждый проект был автономным, т.е. я хотел бы иметь возможность проверять и компилировать каждый проект сам по себе (каждый со своими зависимостями, конечно).

Я думал о сопоставлении каждого проекта в репозитории, а затем ссылался на зависимости с подмодулями, но я вижу следующие проблемы с этим подходом:

  • При проверке Супер со всеми его зависимостями я получаю три копии Core.
  • Поскольку подмодули полностью независимы, каждая из этих трех копий может указывать на разные версии Core, и это будет беспорядок.

Итак... Я что-то упустил? Не понял ли я подмодулей git или неправильно использовал их? Есть ли другое решение этой проблемы (кроме использования двоичных зависимостей)?

4b9b3361

Ответ 1

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

Если Super зависит от Core, его зависимость Core должна "переопределять" те, которые A и B имеют с Core.

Единственный способ подражать этому - создать свой суперпроект так, как вы это сделали,
и, чтобы удалить подмодуль Core of A и B.
(что означает, что теперь Super зависит от A 'и B', A 'является A без ядра, B' является B без ядра)

Ответ 2

Хранилища

git должны быть достаточно атомарными в том смысле, что каждый репозиторий является автономным объектом для определенной цели. Какова цель суперпроекта, кроме объединения проектов A и B? Если нет ничего уникального (т.е. Файлов, которые не находятся ни в A, B, ни в Core), то он довольно избыточный.

EDIT: поскольку подмодули git особенно болезненны в одном месте, в котором я работал, мы создали собственную систему зависимостей, которая отслеживает зависимые репозитории через текстовые файлы. Мы настраиваем его так, чтобы он всегда отслеживал ветвь ветки, а не конкретную фиксацию.

Мы смогли настроить все наши проекты, как если бы они были частью суперпроекта следующим образом:

Super
|-A
|-B
|-Core

Проекты будут ссылаться друг на друга с использованием относительных путей, например. ../A/include.h. Проверка repo A не будет работать, вам нужно будет создать другое "супер" репо для работы только с A:

AWorking
|-A
|-Core

EDIT Еще одна причина такого поведения в git заключается в том, что он не может отслеживать вещи, которые находятся выше корневого каталога репо (то есть над папкой, содержащей папку .git), что определенно будет требуется, если вы хотите, чтобы ваши суперпроекты и подпроекты ссылались на одни и те же репозитории.

Ответ 3

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

Git подходит для отслеживания деревьев. Зависимые отношения между проектами могут (и, скорее всего, делать) формировать график. Дерево - это график, но график не обязательно является деревом. Поскольку ваша проблема заключается в том, как эффективно представлять график, дерево не лучший инструмент для работы.

Здесь может работать подход:

Проект Git имеет каталог .gitmodules, в котором он записывает "подсказки", в которых указывается, от каких проектов зависит фиксация, где они могут быть найдены, и какого пути внутри проекта они должны быть вставлены. (http://osdir.com/ml/git/2009-04/msg00746.html)

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

В этом подходе используются символические ссылки для выхода из формы дерева и построения графика. Если мы записываем ссылки непосредственно в репозитории Git, у нас были бы относительные пути, специфичные для нашей локальной настройки, записанные в отдельных проектах, и проекты не были бы "полностью независимыми", как вы хотели. Следовательно, script для динамической сборки символических ссылок.

Я думаю, что этот подход может помешать Git нежелательными способами, поскольку мы взяли пути, в которых он рассчитывает найти одно, и вместо этого вместо этого поставить что-то еще. Возможно, мы могли бы .gitignore пути символической ссылки. Но теперь мы дважды записываем эти пути и нарушаем DRY. На этом этапе мы также довольно далеко от того, чтобы притворяться, что используем подмодули. Мы могли записывать зависимости в другом месте в каждом проекте и оставлять файл .gitmodules для вещей, ожидаемых Git. Таким образом, мы создадим собственный файл, скажем,.dependencies, и каждый проект может указать свои зависимости там. Наш script будет смотреть туда, а затем идти и строить свои символические ссылки.

Хм, я думаю, что, возможно, я только что описал систему управления пакетами ad hoc со своим легким форматом пакетов:)

megamic suggestion кажется хорошим использованием подмодулей Git для меня. Мы имеем дело только с отслеживанием набора здесь, а не с графиком, а набор легко вписывается в дерево. Дерево на уровне одного уровня по существу является родительским node и набором дочерних узлов.

Как вы указали, это не полностью решает проблему, указанную в вашем вопросе. Мы можем разбить два разных типа "эта работа с той" информацией, которую мы, вероятно, интересуемся: 1. Заявление из версии проекта (предположительно автором проекта), в котором говорилось: "Мне нужна версия X проекта Y" 2. Утверждение, используемое вашей собственной установкой сборки: "Я успешно протестировал всю нашу систему с помощью этого набора версий проекта"

megamic answer resolved (2), но для (1) мы все еще хотим, чтобы проекты рассказывали нам, каковы их зависимости. Затем мы можем использовать информацию из (1) для вычисления тех наборов версий, которые мы будем записывать как (2). Это достаточно сложная задача, чтобы гарантировать собственный инструмент, который возвращает нас в системы управления пакетами:)

Насколько я знаю, большинство хороших инструментов управления пакетами создаются для пользователей определенного языка или операционной системы. См. Bundler для пакетов "gem" в мире ruby ​​и apt для пакетов ".deb" в мире Debian.

Если кто-то знает о хорошем нейтральном с нейтральной к нейтральной среде решении, которое хорошо подходит для "полиглота" (http://blog.heroku.com/archives/2011/8/3/polyglot_platform/), мне было бы очень интересно! Я должен опубликовать это как вопрос.

Ответ 4

Я думаю, что вы можете управлять консистенцией следующим образом: определить ветвь "ссылки" или серию тегов с одинаковыми именами во всех ваших "основных" библиотеках (обратите внимание: в вашем примере есть только одна библиотека "Core" ). Затем инструктируйте разработчиков подпроектов (A, B,...) регулярно обновлять базовую версию "Core", как только они смогут.

Перед запуском сборки легко проверьте, что "Core (s)" последовательно используется в A, B, C,..., запустив эти три команды в чистой, рекурсивной, "Супер", проверке верхнего уровня:

# 1.  Switch to the reference version (= "Force" consistency where need be)
git submodule foreach --recursive 'git checkout [origin/]reference || true'

# 2a. Show which inconsistencies you just forced; terse output
git status -s; git submodule foreach --recursive git status -s 2>/dev/null

# 2b. Same but verbose output
git submodule; git submodule foreach --recursive git submodule

# 3. Switch back to versions individually defined by sub-projects 
git submodule update --recursive

Команда "Terse output" 2a выше показывает, какие подпроекты не используют "ссылочную" версию Core.

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

Ответ 5

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

Вы можете прочитать мое полное решение здесь: fooobar.com/questions/123117/...

Ответ 6

Я бы не попытался сопоставить дерево зависимостей с подмодулями - по причинам, которые вы уже обнаружили.

Подмодули отслеживают данную ревизию данной ветки, поэтому они полезны для создания моментального снимка согласованного набора модулей.

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

 tags/
     release1/ 
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]
     release2/
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]

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