Como reverter um ponteiro do Git Submodule para o commit armazenado no repositório que o contém?

128

Eu tenho um submódulo git no meu repositório principal do git. Pelo que entendi, o repositório principal armazena um valor SHA (em algum lugar ...), apontando para o commit específico do submódulo ao qual ele está "vinculado".

Entrei no meu submódulo e digitei git checkout some_other_branch. Eu não tenho idéia de qual compromisso eu vim.

Gostaria de reverter esse ponteiro para que o repositório principal e o submódulo estejam novamente sincronizados.

Meu primeiro instinto (provavelmente ingênuo) foi dizer git reset --hard- isso parece funcionar para todo o resto. Para minha surpresa, não funcionou nesse cenário.

Então eu descobri que posso digitar git diff, anote o SHA ID que o ponteiro do submódulo costumava ter, e então entre no submódulo e git checkout [SHA ID]... mas certamente deve haver uma maneira mais fácil?

Como ainda estou aprendendo sobre os submódulos git, sinta-se à vontade para corrigir minha terminologia se houver palavras para conceitos que eu não conheça.

Smashery
fonte

Respostas:

167

Você deseja atualizar seu submódulo para que fique sincronizado com o que o repositório pai acredita que deveria ser. É para isso que serve o comando update:

Na página de manual do submódulo:

Atualize os submódulos registrados, ou seja, clone os submódulos ausentes e
faça o checkout do commit especificado no índice do
repositório. Isso fará com que os submódulos HEAD sejam destacados, a menos que
--rebase ou --merge está especificado ou o sub-módulo-chave. $ name.update
está definido para rebase ou mesclagem.

Execute isso e tudo deve ficar bem:

git submodule update
Brian Riehman
fonte
4
De alguma forma, para mim eu precisava adicionar --init. Sem ele, os submódulos permaneceriam em um estado com (new commits). Mesmo que meus submódulos já tenham sido inicializados.
Ambidex
@ Ambidex sim, a --initopção é crucial em tudo isso. Eu estava recebendo um nome de usuário e senha solicitados desde que meus submódulos foram clonados em https. Entrei nas duas pastas e configurei os controles remotos para usar o sshprotocolo para checkout.
A-Dubb
1
não funciona se submodule commit hash é modificado & unstaged
tribbloid
pode adicionar --recursive para que você não precise ir a todos os submódulos
Gaspa79
21

Para alterar a confirmação para a qual um submódulo aponta, é necessário fazer check-out dessa versão no submódulo, voltar ao repositório que contém, adicionar e confirmar essa alteração.

Ou, se você quiser que o submódulo esteja na versão para a qual o repositório superior aponta, faça git submodule update --recursive. Adicione --initse você acabou de clonar.

Além disso, git submodulesem um comando submodule, será mostrado o commit para o qual você está apontando. Haverá um - ou um + na frente do commit, se ele não estiver sincronizado.

Se você olhar para uma árvore com um submódulo, poderá ver que o submódulo está marcado como um commitao contrário do resto que são blobs ou árvores.

para ver o que uma confirmação específica aponta para submódulos, você pode:

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

você pode ver o commit ou qualquer outra coisa, se desejar, passando isso para o log, etc (a git-diropção no nível do comando git permite que você pule a necessidade de fazer o cd no submodule):

git --git-dir=Submodule/path log -1 $(<the above statement>)
Adam Dymitruk
fonte
O comando abaixo me ajudou (eu queria ignorar quaisquer mudanças na submodule e no meu módulo também): update submodule git --init --recursive
Rajesh Goel
6

Outro caso em que acabei de encontrar é se há uma mudança sem estágio no submódulo que você deseja descartar. A atualização do sub-módulo git não removerá essa alteração, nem o git reset --hard no diretório pai. Você precisa ir para o diretório do submódulo e fazer um git reset --hard. Portanto, se eu quiser descartar totalmente as alterações não faseadas no pai e no submódulo, faça o seguinte:

No pai:

git reset --hard

git submodule update

No submódulo:

git reset --hard
Benjamin Noffsinger
fonte
5

Use git ls-tree HEADna pasta "superprojeto" para ver em que commit seu submódulo estava originalmente. Em seguida, mude para o diretório do submódulo e use git log --oneline --decoratepara ver em qual filial o commit original está. Finalmente git checkout original-commit-branch.

Usando alguns diretórios de teste que eu configurei, aqui está a aparência dos comandos:

$ 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)

O "superprojeto" mostra o submódulo sm2 no commit, f68bed6mas o sm2 tem seu HEAD em 5b8d48f. O commit do submódulo f68bed6possui três ramificações que podem ser usadas para checkout no diretório do submódulo.

Dan Cruz
fonte
OBRIGADO DAN, PERFEITO!
Alec
1

Eu queria desconsiderar quaisquer alterações no submódulo e no meu módulo também

O comando abaixo me ajudou:

git submodule update --init --recursive
Rajesh Goel
fonte