2009-09-14 4 views
43

Допустим, у меня есть четыре проекта, названные Ядро, , B, Супер. Дерева зависимостей, как это:Git вложенными Подмодули и зависимости

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

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

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

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

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

ответ

12

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

Если Супер зависит от Ядра, его зависимость от Ядра должны «переопределить» те А и В с Core.

Единственный способ эмулировать, что бы создать свой проект Супер, как вы сделали,
и удалить вспомогательный модуль сердцевине А и В.
(то есть супер теперь зависит от А»и B ', A', являющийся A без ядра, B ', являющийся B без ядра)

7

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

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

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

Super 
|-A 
|-B 
|-Core 

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

AWorking 
|-A 
|-Core 

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

+0

Супер - это проект сам по себе. Не думайте, что у него нет контента только потому, что я назвал его Super. –

+1

Но я хочу, чтобы каждый проект был автономным. И мне нравится, что подмодули git привязаны к определенному комманду, а не следуют примеру svn externals, так что изменение в Core не будет немедленно нарушать A, B и Super. –

+1

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

0

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

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

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

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

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

+0

Хорошо ... но я думаю, что это решает другую проблему ... не тот, о котором я прошу. –

6

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

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

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

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

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

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

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

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

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

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

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

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

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

+1

+1 Поскольку ваша проблема заключается в том, как эффективно представлять график, дерево не лучший инструмент для работы. –

2

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

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

# 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 

«Немногословная выход» команда 2а выше основных моментов, которые суб-проект (ы) не используется «ссылка» версию Core.

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

2

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

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

Смежные вопросы