Git submodule head 'ссылка не дерево' ошибка - PullRequest
295 голосов
/ 28 января 2010

У меня есть проект с подмодулем, который указывает на недопустимый коммит: коммит подмодуля остается локальным, и когда я пытаюсь получить его из другого репо, я получаю:

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

Я знаю, каким должен быть подмодуль HEAD, есть ли способ изменить это локально, не нажимая на репо, что имеет коммит 2d7cfbd09fc96c04c4c41148d44ed7778add6b43?

Я не уверен, что мне ясно ... вот похожая ситуация Я нашел.

Ответы [ 13 ]

372 голосов
/ 29 января 2010

Предполагая, что в репозитории подмодуля есть коммит, который вы хотите использовать (в отличие от коммита, на который ссылается текущее состояние суперпроекта), есть два способа сделать это.

Первый требует, чтобы вы уже знали коммит из подмодуля, который вы хотите использовать. Он работает «изнутри наружу», напрямую настраивая подмодуль, затем обновляя суперпроект. Второй работает извне, находя коммит супер-проекта, который изменил подмодуль, а затем сбрасывает индекс супер-проекта для ссылки на другой коммит суб-модуля.

Внутри, снаружи

Если вы уже знаете, какой коммит вы хотите использовать для подмодуля, cd для субмодуля, проверьте нужный вам коммит, затем git add и git commit верните его в супер-проект.

Пример:

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

Упс, кто-то сделал коммит суперпроекта, который ссылается на неопубликованный коммит в подмодуле sub. Каким-то образом мы уже знаем, что хотим, чтобы субмодуль находился в коммите 5d5a3ee314476701a20f2c6ec4a53f88d651df6c. Отправляйся туда и посмотри прямо.

Оформить заказ в подмодуле

$ cd sub
$ git checkout 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
Note: moving to '5d5a3ee314476701a20f2c6ec4a53f88d651df6c' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b <new_branch_name>
HEAD is now at 5d5a3ee... quux
$ cd ..

Так как мы проверяем коммит, это приводит к отсоединению HEAD в подмодуле. Если вы хотите убедиться, что в подмодуле используется ветвь, то используйте git checkout -b newbranch <commit>, чтобы создать и извлечь ветку при фиксации или извлекать нужную ветку (например, одну с желаемой фиксацией на кончике).

Обновление Супер-проекта

Оформление заказа в подмодуле отражается в суперпроекте как изменение рабочего дерева. Таким образом, нам нужно поэтапно изменить индекс супер-проекта и проверить результаты.

$ git add sub

Проверить результаты

$ git submodule update
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

Обновление подмодуля было тихим, потому что подмодуль уже находится в указанной фиксации. Первый diff показывает, что индекс и рабочее дерево совпадают. Третья разница показывает, что единственное поэтапное изменение - это перемещение подмодуля sub в другой коммит.

Commit

git commit

Это фиксирует фиксированную запись субмодуля.


Снаружи, в

Если вы не уверены, какой коммит вам следует использовать из подмодуля, вы можете посмотреть историю в суперпроекте, чтобы вам было легче. Вы также можете управлять сбросом напрямую из супер-проекта.

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

Это та же самая ситуация, что и выше. Но на этот раз мы сосредоточимся на том, чтобы починить его из суперпроекта, а не заглядывать в подмодуль.

Найти Странствующий коммит Супер-проекта

$ git log --oneline -p -- sub
ce5d37c local change in sub
diff --git a/sub b/sub
index 5d5a3ee..e47c0a1 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
+Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
bca4663 added sub
diff --git a/sub b/sub
new file mode 160000
index 0000000..5d5a3ee
--- /dev/null
+++ b/sub
@@ -0,0 +1 @@
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

ОК, похоже, что все пошло не так в ce5d37c, поэтому мы восстановим подмодуль из его родителя (ce5d37c~).

В качестве альтернативы, вы можете взять коммит субмодуля из текста патча (5d5a3ee314476701a20f2c6ec4a53f88d651df6c) и использовать вместо этого описанный выше процесс «изнутри, снаружи».

Оформить заказ в Супер-проекте

$ git checkout ce5d37c~ -- sub

Это сбрасывает запись подмодуля для sub к тому, что было при коммите ce5d37c~ в суперпроекте.

Обновление подмодуля

$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'

Обновление субмодуля прошло нормально (это указывает на отключенную головку).

Проверить результаты

$ git diff ce5d37c~ -- sub
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

Первый diff показывает, что sub теперь то же самое в ce5d37c~. Вторая разница показывает, что индекс и рабочее дерево совпадают. Третий отчет показывает, что единственное поэтапное изменение - это перемещение подмодуля sub в другой коммит.

Commit

git commit

Это фиксирует фиксированную запись субмодуля.

184 голосов
/ 17 октября 2010

попробуйте это:

git submodule sync
git submodule update
15 голосов
/ 16 ноября 2011

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

Менее вероятно, есть проблема с разрешениями, и фиксация не может быть получена (возможно, если вы используете git + ssh).

Убедитесь, что пути подмодулей выглядят нормально в .git / config и .gitmodules.

Последнее, что нужно попробовать - внутри директории подмодуля: git reset HEAD --hard

9 голосов
/ 04 сентября 2014

Возможная причина

Это может произойти, когда:

  1. Подмодуль (ы) были отредактированы на месте
  2. Подмодуль (-и) зафиксирован, , который обновляет хэш подмодуля, на который указывает
  3. Подмодуль (-ы) не выдвинут .

например. как то так получилось:

$ cd submodule
$ emacs my_source_file  # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"

В этот момент должен быть нажат субмодуль.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master

В результате, удаленный пользователь не может обнаружить отсутствующие коммиты, поскольку они все еще находятся на локальном диске.

Решение

Информатор, который изменил субмодуль для push, т.е.

$ cd submodule
$ git push
5 голосов
/ 16 сентября 2014

Я получил эту ошибку, когда сделал:

$ git submodule update --init --depth 1

но коммит в родительском проекте указывал на более ранний коммит.

Удаление папки подмодуля и запуск:

$ git submodule update --init

НЕ решил проблему. Я удалил репо и попробовал снова без флага глубины, и это сработало.

Эта ошибка возникает в Ubuntu 16.04 git 2.7.4, но не в Ubuntu 18.04 git 2.17, TODO находит точную фиксацию фиксации или версию.

4 голосов
/ 29 января 2012

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

1 голос
/ 27 октября 2016

Этот ответ предназначен для пользователей SourceTree с ограниченным опытом работы с терминалом.

Откройте проблемный субмодуль из проекта Git (супер-проект).

Извлеките и убедитесь, что отмечен флажок «Извлечь все теги».

Перебазируйте вытяните ваш проект Git.

Это решит проблему «ссылка не дерево» 9 из 10 раз.Это 1 раз, это не будет, это исправление терминала, как описано в верхнем ответе.

0 голосов
/ 27 июня 2019

Ваша ветка может быть не в курсе, простое решение, но попробуйте git fetch

0 голосов
/ 04 февраля 2018

Просто наткнулся на эту проблему, и ни одно из этих решений не помогло мне. То, что оказалось решением моей проблемы, на самом деле намного проще: обновить Git. Мой был 1.7.1, и после того, как я обновил его до 2.16.1 (последний), проблема ушла без следа! Думаю, я оставляю это здесь, надеюсь, это кому-нибудь поможет.

0 голосов
/ 29 октября 2015

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

Шаги, которые я выполнил, чтобы удалить подмодуль, вдохновленный https://gist.github.com/kyleturner/1563153:

  1. Запустите git rm --cached
  2. Удалить соответствующие строки из файла .gitmodules.
  3. Удалить соответствующий раздел из .git / config.
  4. Удалите теперь неотслеживаемые файлы субмодулей.
  5. Удалить каталог .git / modules /

Опять же, это может быть полезно, если все, что вам нужно, это снова указывать на голову подмодуля, и вы не усложняете задачу, сохраняя локальную копию подмодуля в целости и сохранности. Предполагается, что у вас есть подмодуль «право» в качестве собственного репо, где бы он ни был, и вы просто хотите вернуться к правильному включению его в качестве подмодуля.

Примечание: всегда делайте полную копию своего проекта перед тем, как приступить к подобным манипуляциям или любой команде git, кроме простого коммита или толчка. Я бы посоветовал это со всеми другими ответами, а также в качестве общего руководства git.

...