Как сделать существующий каталог в git-хранилище git-подмодулем

Я очень смущен о git-подмодулях.

В основном моя проблема заключается в том, что я не могу заставить git понять, что ~/main-project/submodule является подмодулем.


У меня есть хороший опыт работы с подмодулями git:
в моем репозитории dotfiles я создал файл.gitmodules в ~/dotfiles-repo и я добавил туда пути и URL-адреса. С тех пор, если я вношу изменения в файлы в подмодулях и запускаю git status, я бы получил что-то вроде: .vim/bundle/auto-complete (new commits) # in red

Я создал файл .gitmodules в ~/main-project но:

  • Если я вношу изменения в ~/main-project/submodule и даже вставляю изменения, я не получаю аналогичный ответ, например, <submodule> (new commits) # in red при запуске git status в ~/main-project. Я просто получаю изменения, которые были сделаны в этих каталогах
  • Когда я нажимаю ссылки на папки в github для этих каталогов, он не направляет меня непосредственно в репозитории, но я остаюсь в том же репозитории.

    1. Может быть, мне не хватает всего. Каковы основные черты подмодулей?
    2. Почему git понимает подмодули в реплике dotfiles, но не в моем другом репо?
    3. Это потому, что я уже сказал git, чтобы добавить файлы в ~/main-project/submodule к индексу?

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

Изменение: это предлагаемое дублирующее решение тоже не сработало, я получил сообщение об ошибке, по которой Updates were rejected because the remote contains work that you do not have locally. Кажется, что @GabLeRoux практически сказал мне нажать <repo-A> на URL-адрес <repo-B>.

Ответ 1

Решение довольно простое. Это было извлечено отсюда.

  1. git rm submodule-dir
    Это удалит все файлы, которые git отслеживал после в submodule-dir
  2. rm -rf submoduledir
    Это приведет к удалению всех других файлов, которые могли быть оставлены в submodule-dir потому что git игнорировал их.
  3. Теперь мы должны зафиксировать, чтобы удалить файлы из индекса:
    git commit
    После фиксации мы очистили файлы, которые git следили и не соблюдались в submodul-dir. Теперь пришло время:
  4. git submodule add <remote-path-to-submodule>
    Это снова добавит подмодуль, но как истинный подмодуль.
  5. На этом этапе было бы неплохо проверить .gitmodules и посмотреть, были ли добавлены подмодули успешно. В моем случае у меня уже был файл .gitmodules поэтому мне пришлось его модифицировать.

РЕДАКТИРОВАТЬ

Так как v2.12.0-rc0, и после этого совершения, Мы получили git submodule absorbgitdirs и именно то, что мне было нужно в то время, когда я разместил этот вопрос.

Это то, что указала эта команда docs:

Если в подмодуле находится каталог git подмодуля, переместите каталог git подмодуля в его путь суперпроектов $GIT_DIR/modules а затем подключите каталог git и его рабочий каталог, установив core.worktree и добавив файл.git, указывающий в каталог git, встроенный в каталог git superprojects.

Поэтому вместо того, чтобы начинать все, как было предложено в предыдущих ответах @DomQ и мной, можно просто добавить run:

  1. Не удаляя из индекса подмодуль, добавьте url подмодуля в .gitmodules и в .git/config с
    git submodule add <url> <path>
  2. Переместите подмодуль $GIT_DIR (.git в обычных репозиториях) в .git/modules/<path> с помощью
    git submodule absorbgitdirs <path>

Ответ 2

В принципе нет лучшего способа, чем притворяться, что начать:

  1. обеспечить, чтобы все было совершено повсюду
  2. переместите свой субрепозиторий в сторону
  3. git submodule add из удаленного репозитория
  4. cd mysubmodule
  5. git fetch../wherever/you/stashed/the/sub-repository/in/step-1
  6. git merge FETCH_HEAD

Чтобы объяснить, почему это так, мне кажется, чем требуется более глубокое понимание того, какие подмодули необходимы, чем то, что можно почерпнуть из справочной страницы git-submodule(1) (или даже соответствующей главы из книги Git). Я нашел более подробные объяснения в этом блоге, но, поскольку этот пост немного длинный, я беру на себя смелость, суммируя их здесь.

На низком уровне подмодуль git состоит из следующих элементов:

  • Объект фиксации в верхней части дерева подмодулей,
  • (В последних версиях Git) Подкаталог в .git/modules для размещения объектов Git для подмодуля,
  • Запись в .gitmodules конфигурации .gitmodules.

Объект фиксации содержится (или, точнее, ссылка SHA1) в родительском дереве. Это необычно, так как вещи обычно происходят наоборот, но это объясняет, почему вы видите каталог в главном git status хранилища после того, как вы выполнили фиксацию в подмодуле. Вы также можете провести некоторые эксперименты с git ls-tree чтобы более подробно наблюдать этот объект фиксации.

Подкаталог в .git/modules находится в поддиректории .git в подмодуле; и на самом деле в подмодуле есть файл .git который указывает на первый, используя gitdir: Это поведение по умолчанию с версии 1.7.8 Git. Не уверен, почему все будет не просто работать, если вы просто сохранили отдельный каталог .git, за исключением случаев, отмеченных в примечаниях к выпуску, которые, вероятно, столкнулись бы с проблемой при переключении между ветвью, которая имеет подмодуль, а другая - нет.

Файл .gitmodules предоставляет URL-адрес, который git submodule update --remote и друзья должны извлекать; который, очевидно, отличается от основного набора репозиториев. Также обратите внимание, что .gitmodules копируется в .git/config командой git submodule sync и другими командами, которые вызывают это за кулисами.

Хотя довольно легко выполнить необходимые изменения вручную для .gitmodules + .git/config, а также для .git/modules + mysubmodule/.git (и на самом деле для последнего есть даже git submodule absorbgitdirs), там на самом деле не является фарфором для создания только объекта фиксации дерева. Следовательно, предлагаемое решение, перемещая + повторные изменения, представленные выше.

Ответ 3

Чтобы ответить на ваши вопросы в порядке:

  1. Цель подмодулей по GitHub. Разумеется, он был разработан, чтобы быть концептуальным дочерним репозиторием (который можно почти рассматривать как любой другой файл), то есть версией, управляемой родительским репозиторием, где родительский объект отслеживает текущий идентификатор фиксации подмодуля (дочерний репозиторий) чем содержание.
  2. Это, скорее всего, потому, что вы уже добавили файлы в индекс репозитория. В этом случае решением является git rm --cached submodule-name/. Затем создайте промежуточную фиксацию, а затем добавьте папку в качестве репозитория: git add submodule-name (обратите внимание, что в случае субмодулей нет подслоя после подмодуля).
  3. Да :)

Ответ, который вы упомянули, может также исправить историю ваших совершений:

  1. Преимущества:

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

  1. Недостатки:

Если история фиксации изменена, все остальные участники также должны будут повторно клонировать проект, так как они получат конфликты слияния или хуже; повторная постановка проблемы возвращается к проекту.