Подмодуль Git находится в состоянии "отсоединенной головки" после обновления клонирования и подмодуля
Когда я клонирую свой репо git, один из подмодулей находится в ветки со странным именем, что, я думаю, означает, что у него есть " отсоединенная голова" (я даже не уверен что это значит).
Если я проверяю свою основную ветвь для подмодуля, тогда запустите "git submodule update --init --recursive
", это произойдет снова.
Кто-нибудь знает, что происходит?
Ответы
Ответ 1
Содержимое каталогов git хранится в манифесте простого текстового файла (например, списки каталогов), называемые деревьями, которые выглядят следующим образом: где капли - это содержимое файлов, а деревья - еще больше деревьев, подобных этому:
100644 blob 0c31be662540ce902cee106f86bfdeef519fc662 .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347 .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd foo
040000 tree 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823 bar
Если bar был подмодулем, а не только в каталоге, дерево, содержащее его, будет указано следующим образом:
100644 blob 0c31be662540ce902cee106f86bfdeef519fc662 .gitignore
100644 blob 1d364edf530c2238e79162bf2d9f30c2af610347 .gitmodules
040000 tree fc6bc39202ec20228e9135cd426110c558b625cd foo
040000 commit 2f9fc460f3a2370ed45b39b2bcaaf9b6e746b823 bar
Обратите внимание, что вместо того, чтобы bar является деревом, теперь он является фиксацией (в подмодуле). Это все git хранит о субмодуле на уровне дерева/фиксации, поэтому он не может знать, в какую ветвь была включена фиксация. На самом деле сохранение имен веток не может быть выполнено. Они могут измениться. Кроме того, если вы проверите старую фиксацию в своем репо, которая также должна отбросить подмодуль, если ветвь вернется в подмодуль? Это заставило бы коммиты после этого нового местоположения ветки на незарегистрированную территорию.
Ветви для людей, чтобы использовать их, чтобы понять смысл DAG, и где есть определенные линии мысли. git все равно, как мы ссылаемся на коммиты. Он нуждается в конкретном месте, чтобы вы могли безопасно перемещать содержащее репо и знать, что подмодуль всегда будет проверен там, где он был в то время. Единственная истина - хэш.
Ответ 2
Подмодуль всегда извлекается как отдельный заголовок (см. " Почему git отсоединил мою голову? "), Поскольку индекс родительского репо содержит только SHA1 в качестве специальной записи в своем индексе, как объяснил ответ Гэри Фикслера.
Даже если вы сконфигурируете свой подмодуль, чтобы он следовал за веткой (или преобразовал существующий подмодуль, чтобы следовать за веткой), git submodule update --remote
будет git submodule update --remote
последний SHA1 этой удаленной ветки, но результатом по умолчанию будет отдельный HEAD.
Только добавив --merge
или --rebase
к этой команде (git submodule update --remote (--merge / --rebase)
), вы получите git submodule update --remote (--merge / --rebase)
, как видно из ответа Симбы): по умолчанию master
ветка.
Если вы не обновляете этот путь (git submodule update --remote (--merge / --rebase)
), то вам нужно зайти в этот подмодуль и создать там ветку.
Если вы хотите внести свой вклад в упомянутый подмодуль (делать в нем новые коммиты), будет хорошей идеей создать новую ветку.
cd mySubmodule
git checkout -b aNewBranch
# work
git add .
git commit -m "new commits"
git push -u origin aNewBranch
# record the new submodule state in the parent repo:
cd ..
git add mySubmodule
git commit -m "new state of mySubmodule"
git push
Примечание для Git 2.16 (Q1 2018): " git checkout --recursive
" может перезаписывать и перематывать историю ветки, которая оказывается извлеченной в репозиториях подмодулей, что может быть нежелательно.
Отсоедините HEAD
но все же разрешите рекурсивную проверку в таком случае успешно.
Смотрите коммит 57f22bf (28 июля 2017 г.) и коммит 3ef2538 (24 июля 2017 г.) Стефана Беллера (stefanbeller
).
(Объединено с Junio C Hamano - gitster
- в коммите 0b75572, 06 декабря 2017 г.)
рекурсивные подмодули: отсоединить HEAD от нового состояния
Когда подмодуль находится в ветки и в его суперпроекте выполняется рекурсивная проверка, ветвь подмодуля обновляется до того, что проверяет суперпроект.
Это очень неожиданно в текущей модели Git, так как, например, " submodule update
" всегда отсоединяет подмодуль HEAD.
Несмотря на то, что в будущем планируется отключить подмодуль HEADS, текущее поведение действительно плохое, так как оно не соответствует ожиданиям пользователей и не проверяет потерю коммитов (только для восстановления через reflog).
Отсоединяйте ГОЛОВКУ безоговорочно в подмодуле при его обновлении.
Ответ 3
Для пользователей Sourcetree - вы будете наблюдать такое же поведение - клон даст вам подмодули в отдельном состоянии. Поскольку VonC упоминает в своем ответе, если вы хотите внести вклад в подмодуль, вам нужно выполнить некоторые дополнительные шаги.
Помимо создания новой ветки с точки подмодуля SHA-1, в большинстве случаев вам просто нужно проверить голову существующей ветки. Это будет мастер, если подмодуль не настроен на выполнение определенной ветки.
Вы можете либо открыть каждый подмодуль, либо вручную проверить их соответствующие ветки, либо создать собственное действие для него (рекурсивно!):
![enter image description here]()
Script для запуска
cmd
Параметры
/c %LOCALAPPDATA%\Atlassian\SourceTree\git_local\bin\sh.exe --login -i -c "git pull; git submodule foreach -q --recursive 'toplevel=\"$(git rev-parse --show-toplevel)\"; branch=\"$(git config -f $toplevel/.gitmodules submodule.$name.branch)\"; [ \"$branch\" = \"\" ] && branch=master; git checkout $branch; git fetch; git merge FETCH_HEAD;'"""
Это проверит любые подмодули в вашем проекте и проверит ветку, на которую они указывают (или мастер, если они не указывают ветку). Он рекурсивный, поэтому любые подмодули, содержащие подмодули, также будут обрабатываться.
Как я узнал в более раннем сообщении, требуется дополнительная пара кавычек на конце.
Ответ 4
Добавление параметра branch
в .gitmodule
НЕ связано с отсоединенным поведением подмодулей вообще.
Из git submodule --help
отключение HEAD является поведением по умолчанию git submodule update --remote
.
Во-первых, нет необходимости указывать отслеживаемую ветвь. origin/master
является веткой по умолчанию для отслеживания.
--remote
Вместо того, чтобы использовать суперпроект, записанный SHA-1, для обновления субмодуля, используйте статус ветки удаленного отслеживания субмодуля. Используется удаленный филиал (branch.<name>.remote
), по branch.<name>.remote
используется origin
. Удаленная ветвь по умолчанию использовала master
.
Зачем
Так почему же HEAD отключается после update
? Потому что по умолчанию в submodule.$name.update
используется checkout
.
--checkout
Оформить коммит, записанный в суперпроекте на отдельном HEAD в субмодуле. Это поведение по умолчанию, основное использование этого параметра - переопределение submodule.$name.update
когда установлено значение, отличное от checkout
.
Как
Если вы хотите, чтобы субмодуль автоматически объединялся с удаленной ветвью, используйте --merge
или --rebase
.
--merge
Эта опция действительна только для команды обновления. Объединить фиксацию, записанную в суперпроекте, с текущей веткой субмодуля. Если эта опция задана, подмодуль HEAD не будет отсоединен.
--rebase
Перебазировать текущую ветвь на коммит, записанный в суперпроекте. Если эта опция задана, подмодуль HEAD не будет отсоединен.
Все, что вам нужно сделать, это,
git submodule update --remote --merge
# or
git submodule update --remote --rebase
Также есть возможность сделать --merge
или --rebase
поведением по умолчанию для git submodule update
, установив submodule.$name.update
для merge
или rebase
.
Вот пример того, как .gitmodule
поведение обновления по умолчанию для обновления субмодуля в .gitmodule
.
[submodule "bash/plugins/dircolors-solarized"]
path = bash/plugins/dircolors-solarized
url = https://github.com/seebi/dircolors-solarized.git
update = merge # <-- this is what you need to add
Весь мой ответ основан на руководстве. git submodule --help
.