В идеале, если вы клонируете репозиторий и его подмодули, но затем проверяете фиксацию, в которой подмодули не используются, Git удалит каталог подмодулей. Однако существует проблема с историей Git, связанная с этим.
В следующем обсуждении помните, что подмодуль является репозиторием Git сам по себе. Это просто репозиторий Git, текущий коммит которого контролируется другим Git, который мы называем суперпроектом . Суперпроект Git имеет список используемых подмодулей, и для каждого подмодуля фиксация внутри этого подмодуля для проверки / переключения внутри этого подмодуля. Помните также, что репозиторий Git - это, по сути, пара баз данных. Одна база данных, обычно гораздо более крупная, содержит все внутренние объекты Git: коммиты и их файлы, а также другие вспомогательные внутренние объекты, составляющие историю. Другая база данных содержит имена, такие как имена веток и тегов, и их сопоставления с коммитами. Поверх этих двух баз данных есть большой уровень программного обеспечения для управления исходным кодом, но сами базы данных важны для процесса: go ничто не может нигде, если только коммиты не существуют и не могут быть найдены.
Следовательно, репозиторий - это набор данных, хранящийся в каталоге .git
. Репозиторий голый - это репозиторий, который состоит только из каталога .git
: это то, что обычно можно найти на серверах и сайтах хостинга, таких как GitHub или Bitbucket. Репозиторий разработчика состоит как из каталога .git
, так и из рабочего дерева или , где Git может извлекать файлы из некоторого коммита, чтобы вы могли с ними работать. , и где вы можете работать с этими файлами и, таким образом, делать новые коммиты.
Обратите внимание, что каталог .git
для репозитория верхнего уровня (суперпроекта) обычно находится в рабочем дереве этого репозитория . То есть наверху вашего рабочего дерева находится скрытый каталог .git
, содержащий репозиторий.
В современном Git - «современный» определяется здесь как Git версии 2 и более поздних, хотя кое-что из этого также было обнаружено в последних версиях 1.x - обычная структура хранилища для репозитория и его подмодулей (если есть) обычно хранит все репозитории подмодулей в каталоге .git
, в котором хранится суперпроект. Механизм для этого называется поглощением: родительский суперпроект «поглощает» репозиторий подмодуля. Следовательно, если родительский репозиторий находится в path/to/repo/.git
, а рабочее дерево подмодуля находится в path/to/repo/subm/
, фактическое репозиторий для path/to/repo/subm/
будет не path/to/repo/subm/.git/
, а path/to/repo/.git/modules/subm/
. Вы обнаружите , что существует простой файл с именем path/to/repo/subm/.git
; этот простой файл содержит информацию о пути к репозиторию, которая требуется Git при работе с подмодулем.
Однако в очень старых версиях Git, некоторые из которых все еще используются, это не случай: репозиторий подмодуля фактически хранится в path/to/repo/subm/.git
. Более того, если вы создаете пару новый суперпроект и подмодуль, вы можете сделать это, запустив:
mkdir path/to/repo
cd path/to/repo
# now get into path/to/repo/subm and create the submodule first
mkdir subm; cd subm; git init
echo "submodule for whatever" > README.txt
git add README.txt
git commit -m initial
git push -u ... # create submodule on the hosting system
# now back to path/to/repo
cd ..
git init
echo "new project" > README.txt
git add README.txt
git commit -m initial
# include the submodule
git submodule add <url> subm
git commit -m "add submodule"
Сделав это, вы еще не «поглотили» подмодуль в основной репозиторий. Фактический репозиторий подмодулей, включая все его коммиты и другие данные, все еще находится в path/to/repo/subm/.git/
. Вы должны запустить:
git submodule absorbgitdirs
, чтобы переместить репозиторий подмодуля в path/to/repo/.git/modules/
. (И если в вашей команде git submodule
отсутствует подкоманда absorbgitdirs
, у вас есть версия Git, которая не поддерживает поглощающие подмодули.)
Теперь, если у вас есть подмодуль поглощенного стиля, и вы использовали git checkout
, чтобы проверить фиксацию суперпроекта, которая, как и наша первая фиксация в суперпроекте выше, на самом деле не имеет подмодуля, ваш суперпроект Git может безопасно удалить весь path/to/repo/subm/
дерево, включая файл .git
. Фактический подмодуль, включая все сделанные вами коммиты, но еще не отправленные, безопасно хранится в основном репозитории Git. Но если по какой-либо причине у вас есть подмодуль без , удаление path/to/repo/subm/
также приведет к удалению всех файлов в path/to/repo/subm/.git/
, тем самым удалив весь репозиторий.
Это явно опасно, а Git просто этого не делает, даже если субмодуль был поглощен. Возможно, Git должен сделать это для случая поглощенного подмодуля, но этого не происходит, по крайней мере, до текущих версий Git (2.27).