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

Дублирующие подмодули с Git

У меня есть проект в 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

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

4b9b3361

Ответ 1

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

# 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, если вы не вмешиваетесь.

Ответ 2

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, что является поведением, которое я предпочитаю в моем случае.

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

ПРЕДОСТЕРЕЖЕНИЯ

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

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

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