Как разрешить конфликт подмодуля git, если подмодуль не инициализирован

У меня две ветки A и B. Оба содержат подмодуль (в папке sub), однако при разных коммитах (которые не перескакивают с одного на другой).

A  B
| /
BASE

Я проверил A, но подмодуль еще не инициализирован. Теперь я объединяю B и получаю конфликт на подмодуле.

$ git status
Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   sub

Выдача git checkout --ours sub ничего не делает (если подмодуль инициализирован, он работает, также git checkout-index -f --stage=2 -- sub не работает). git add sub вызывает ошибку error: pathspec 'sub' did not match any file(s) known to git..

$ git diff sub
diff --cc sub
index 533da4e,ab2af77..0000000
--- a/sub
+++ b/sub
@@@ -1,1 -1,1 +1,1 @@@
- Subproject commit 533da4ea00703f4ad6d5518e1ce81d20261c40c0
 -Subproject commit ab2af775ec467ebb328a7374653f247920f258f3
++Subproject commit 0000000000000000000000000000000000000000

git submodule init -- sub ничего не делает. Также git submodule update --init --force -- sub не работает: Skipping unmerged submodule sub.

Итак, как я могу разрешить этот конфликт подмодуля (без прерывания слияния и повторения после инициализации подмодуля)?

Ответ 1

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

Один из способов обновления индекса - git reset. Если вы знаете фиксацию, в которой подмодуль находится в состоянии, которое вы хотите, вы можете использовать это. Например, любое из следующего может быть тем, что вы хотите:

git reset master -- sub
git reset [email protected]{upstream} -- sub
git reset HEAD -- sub
git reset MERGE_HEAD -- sub

Другой вариант - обновить индекс напрямую, используя команду сантехника git update-index. Для этого вам нужно знать, что объект типа gitlink (т.е. Запись каталога в родительском репозитории, который указывает на подмодуль) равен 0160000. Нет способа понять это из первых принципов, но вы можете понять это из git ls-files -s или следующую ссылку (см. "1110 (gitlink)" под 4-битным типом объекта: https://github.com/gitster/git/blob/master/Documentation/technical/index-format.txt

Чтобы использовать этот подход, определите хэш, который вы хотите установить подмодулем, затем выполните, например:

git update-index --cacheinfo 0160000,533da4ea00703f4ad6d5518e1ce81d20261c40c0,sub

Ответ 2

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

В вашем случае вы не можете иметь как правильное содержимое результата слияния по пути подмодуля, так и никакого содержимого. Единственное, что необходимо, это иметь репо на этом пути с правильным идентификатором commit в HEAD. Содержащее репо действительно не могло бы заботиться о том, откуда взялся репо из подмодуля на этом пути, единственное, что имеет значение на данном этапе, это то, что commit id в HEAD.