Двойные подмодули с Git - PullRequest
21 голосов
/ 07 ноября 2010

У меня есть проект в Git, в котором есть несколько подмодулей, и мне нужно, чтобы эти подмодули были загружены и файлы были доступны для использования основного проекта, а чтобы подмодули работали, мне нужны их собственные подмодули и т.д. Чтобы установить это, я рекурсивно инициализирую подмодули, используя git submodule update --init --recursive.

Однако я заметил, что многие из моих подмодулей имеют общие зависимости, выглядя примерно так в псевдокоде (alpha -> beta означает, что alpha имеет подмодуль beta)

my project -> submodule a -> submodule m
           -> submodule b -> submodule m
                          -> submodule n -> submodule x
           -> submodule c -> submodule x

Мой вопрос: есть ли способ избежать этого дублирования, используя только git, при этом сохраняя (хотя бы одну копию) файлы для каждого подмодуля?

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

В идеале я бы хотел упростить его до:

my project -> submodule a -> symlink(submodule m)
           -> submodule b -> symlink(submodule m)
                          -> symlink(submodule n)
           -> submodule c -> symlink(submodule x)
           -> submodule m
           -> submodule n -> symlink(submodule x)
           -> submodule x

Заранее спасибо за любые предложения!

Ответы [ 2 ]

7 голосов
/ 07 ноября 2010

Это не встроено в git, но вы определенно можете сделать это с помощью символических ссылок, как вы говорите.Возможно, вы захотите взглянуть на git new-workdir (из каталога contrib git), что по сути и делает это.Он не знает ничего общего с подмодулями, но подмодуль не знает, что это подмодуль - это родительское репо, которое знает об этом.Я не пробовал это, но я вполне уверен, что вы могли бы использовать это как-то так:

# remove the target first (new-workdir will refuse to overwrite)
rm -rf submodule_b/submodule_m

#               (original repo)         (symlinked repo)
git new-workdir submodule_a/submodule_m submodule_b/submodule_m

Это работает путем символической ссылки по существу всего каталога .git;заметная вещь, которая не является символической ссылкой, это HEAD;в двух каталогах можно проверить разные вещи, но использовать одни и те же ссылки и объекты.

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

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

3 голосов
/ 22 апреля 2012

git-new-workdir не может быть хорошим решением, как обсуждалось здесь: http://comments.gmane.org/gmane.comp.version-control.git/196019

Это не сработало для меня в git 1.7.10.

Я решил это для своего использования-при использовании жестких ссылок.Я использую OS X, и файловая система позволяет создавать жесткие ссылки на каталоги: https://github.com/darwin/hlink

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

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

CAVEATS :

1) Это прекрасно работает, пока работают относительные пути в .git.Другими словами, вы можете жестко связывать только подмодули, находящиеся на одном уровне каталогов в дереве каталогов.Это был мой случай.Я предполагаю, что вы можете легко исправить это, изменив .gitfiles своей жесткой связью.Примечание: Это не должно быть проблемой до git 1.7.10, потому что ранее .git подмодуля был автономным каталогом, а не просто открытым текстом .git, указывающим куда-то еще.

2) Жесткие ссылки могут создавать некоторые несовместимости.Например, TimeMachine запутывается, потому что он использует жесткие ссылки для контроля версий.Убедитесь, что вы исключили форму каталога вашего проекта TimeMachine.

Вот пример моей грабли, выполняющей работу: https://github.com/binaryage/site/blob/3ef664693cafc972d05c57a64c41e89b1c947bfc/rakefile#L94-115

...