Дублирующие подмодули с 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
Заранее благодарим за любые предложения!
Ответы
Ответ 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