Как вернуть указатель подмодуля Git на фиксацию, хранящуюся в содержащем репозитории?

128

У меня есть подмодуль git в моем основном репозитории git. Насколько я понимаю, в основном репо хранится значение SHA (где-то ...), указывающее на конкретный коммит подмодуля, с которым он «связан».

Я вошел в свой подмодуль и набрал git checkout some_other_branch. Понятия не имею, из какого коммита я пришел.

Я хотел бы вернуть этот указатель, чтобы основное репо и подмодуль снова синхронизировались.

Моим первым (вероятно, наивным) инстинктом было сказать git reset --hard- похоже, это работает для всего остального. К моему удивлению, для этого сценария это не сработало.

Итак, я понял, что могу печатать git diff, запомнить идентификатор SHA, который использовался указателем подмодуля, а затем перейти к подмодулю и git checkout [SHA ID]... но, конечно, должен быть более простой способ?

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

Smashery
источник

Ответы:

167

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

На странице руководства по подмодулю:

Обновите зарегистрированные подмодули, т.е. клонируйте отсутствующие подмодули и
проверить фиксацию, указанную в индексе содержащего
репозиторий. Это приведет к отсоединению подмодулей HEAD, если
--rebase или --merge или подмодуль ключа. $ name.update
настроен на перебазирование или слияние.

Запустите это, и все должно быть хорошо:

git submodule update
Брайан Риман
источник
4
Как-то мне нужно было добавить --init. Без него субмодули остались бы в состоянии с (new commits). Хотя мои подмодули уже были инициализированы.
Ambidex
@Ambidex да --initопция во всем этом решающая. Мне предлагали ввести имя пользователя и пароль, так как мои подмодули были клонированы по https. Я вошел в обе папки и настроил пульты на использование sshпротокола для проверки.
A-Dubb
1
не работает, если хеш фиксации подмодуля изменен и неустановлен
tribbloid
можно добавить --recursive, чтобы вам не нужно было переходить ко всем подмодулям
Gaspa79
21

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

Или, если вы хотите, чтобы подмодуль был в версии, на которую указывает верхний репо, сделайте это git submodule update --recursive. Добавьте, --initесли вы только что клонировали.

Кроме того, git submoduleбез подмодуля команда покажет вам фиксацию, на которую вы указываете. Перед коммитом будет - или +, если он не синхронизирован.

Если вы посмотрите на дерево с подмодулем в нем, вы увидите, что подмодуль помечен как commitв отличие от остальных, которые являются каплями или деревьями.

чтобы увидеть, какие точки фиксации связаны с подмодулями, вы можете:

git ls-tree <some sha1, or branch, etc> Submodule/path

затем вы можете увидеть фиксацию или что-то еще, если хотите, передав это в журнал и т.д. ( git-dirопция на уровне команды git позволяет вам пропустить необходимость перехода к подмодулю с cd):

git --git-dir=Submodule/path log -1 $(<the above statement>)
Адам Димитрук
источник
Приведенная ниже команда помогла мне (я хотел проигнорировать любые изменения в подмодуле, а также в моем модуле): git submodule update --init --recursive
Раджеш Гоэль
6

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

В родительском:

git reset --hard

git submodule update

В подмодуле:

git reset --hard
Бенджамин Ноффсингер
источник
5

Используйте git ls-tree HEADв папке «superproject», чтобы увидеть, в каком коммите изначально находился ваш подмодуль. Затем перейдите в каталог подмодуля и используйте, git log --oneline --decorateчтобы увидеть, в какой ветви находится исходный коммит. И, наконец, git checkout original-commit-branch.

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

$ git --version
git version 1.7.4.1
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   sm2 (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git ls-tree HEAD
100644 blob 76813a07ae558db274cefc6d903ec24323fdeb0d    .gitmodules
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main
160000 commit 7c5889497938cd5699a9234a98ee93947e52b1ed  sm1
160000 commit f68bed61cba6f94cef57554f2cf46a45a4a0d337  sm2
$ cd sm2
$ git log --oneline --decorate
5b8d48f (HEAD, foo1) foo1.1
f68bed6 (origin/master, origin/HEAD, master) Initial commit.
$ git checkout master
Switched to branch 'master'
$ cd ..
$ git status
# On branch master
nothing to commit (working directory clean)

«Суперпроект» показывает подмодуль sm2 при фиксации, f68bed6но sm2 имеет его HEAD в 5b8d48f. У фиксации подмодуля f68bed6есть три ветви, которые можно использовать для проверки в каталоге подмодуля.

Дэн Круз
источник
СПАСИБО ДЭН, ИДЕАЛЬНО!
Алек
4

Ответ здесь как-то не решил мою конкретную проблему с подмодулем, поэтому, если это произойдет и с вами, попробуйте следующее ...

 git submodule foreach git reset --hard

https://kalyanchakravarthy.net/blog/git-discard-submodule-changes/

MichaelChan
источник
1
хороший однострочный!
user8162
1

Я хотел игнорировать любые изменения в подмодуле, а также в моем модуле

Следующая команда мне помогла:

git submodule update --init --recursive
Раджеш Гоэль
источник