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

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

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

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

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

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

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

6 ответов


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

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

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


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

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

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

Super
|-A
|-B
|-Core

проекты будут ссылаться друг на друга, используя относительные пути, например,../A/include.h. Проверка РЕПО A не будет работать, вам придется создать еще одно" супер " РЕПО для работы только на A:

AWorking
|-A
|-Core

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


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

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

вот подход, который может сработать:

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

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

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

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

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

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

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

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

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

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


Я думаю, вы можете управлять согласованностью следующим образом: определите ветвь "ссылки" или серию тегов с одинаковыми именами во всех ваших "основных" библиотеках(примечание: в вашем примере есть только одна "основная" библиотека). Затем проинструктируйте разработчиков подпроектов (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

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

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


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

вы можете прочитать мое полное решение здесь: https://stackoverflow.com/a/10265084/84283


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

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

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

 tags/
     release1/ 
           |-> A@1.0
           |-> B@1.1
           |-> C@1.2
     release2/
           |-> A@2.0
           |-> B@1.3
           |-> C@1.5

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