Git diff diz que o subprojeto está sujo

227

Acabei de executar um diff git e estou recebendo a seguinte saída para todos os meus aproximadamente 10 submodules

diff --git a/.vim/bundle/bufexplorer b/.vim/bundle/bufexplorer
--- a/.vim/bundle/bufexplorer
+++ b/.vim/bundle/bufexplorer
@@ -1 +1 @@
-Subproject commit 8c75e65b647238febd0257658b150f717a136359
+Subproject commit 8c75e65b647238febd0257658b150f717a136359-dirty

O que isto significa? Como faço para corrigir isso?

mrwooster
fonte

Respostas:

268

Conforme mencionado na publicação no blog de Mark Longair, Git Submodules Explained ,

As versões 1.7.0 e posteriores do git contêm uma alteração irritante no comportamento do submódulo git.
Os submódulos agora são considerados sujos se tiverem arquivos modificados ou não rastreados , enquanto anteriormente só seria o caso se HEAD no submódulo apontasse para a confirmação incorreta.

O significado do sinal de mais ( +) na saída do submódulo git mudou, e na primeira vez que você se deparar com isso, leva um tempo para descobrir o que está acontecendo de errado, por exemplo, olhando através de registros de alterações ou usando git bisect no git .git para encontrar a alteração. Teria sido muito mais gentil com os usuários introduzir um símbolo diferente para "na versão especificada, mas suja".

Você pode corrigi-lo:

  • confirmando ou desfazendo as alterações / evoluções em cada um dos seus submódulos, antes de voltar ao repositório pai (onde o diff não deve mais relatar arquivos "sujos"). Para desfazer todas as alterações no seu submódulo apenas cdno diretório raiz do submódulo e fazergit checkout .

    O dotnetCarpenter comenta que você pode fazer um:git submodule foreach --recursive git checkout .

  • ou adicione --ignore-submodulesao seu git diff, para ignorar temporariamente esses submódulos "sujos".

Novo no Git versão 1.7.2

Como Noam comenta abaixo , esta pergunta menciona que, desde a versão 1.7.2 do git, você pode ignorar os submódulos sujos com:

git status --ignore-submodules=dirty
VonC
fonte
2
Também é uma coisa boa a saber: você ainda pode executar git commit -asem ter que se preocupar em adicionar essas alterações. Embora estejam marcados com Mna frente, eles não acabarão no seu commit.
Gtaarik #
1
Para mim, eu tive que entrar em cada submódulo sujo e executar git clean -id.
GDP2 13/11/19
1
@ PIB2 Que você pode vestir em uma linha, com git submodule foreach --recursive git clean -id(a ser testado em um repo primeiro backup;))
VonC
1
O caso em que eu continuava vendo isso inexplicavelmente, o que estava acontecendo era que eu tinha arquivos não rastreados que não estavam no submódulo .gitignore. Adicioná-los lá ou à minha lista global de ignorados corrigidos.
Ben
21

Também remover o submódulo e depois executar git submodule inite git submodule updateobviamente fará o truque, mas nem sempre é apropriado ou possível.

user1178907
fonte
1
Isso funcionou para mim quando converti algumas pastas existentes em submódulos e depois puxei para outra máquina que ainda possuía as pastas antigas.
Roger Lipscombe
18

Para ignorar todos os arquivos não rastreados em qualquer submódulo, use o seguinte comando para ignorar essas alterações.

git config --global diff.ignoreSubmodules dirty

Ele adicionará a seguinte opção de configuração à sua configuração local do git:

[diff]
  ignoreSubmodules = dirty

Mais informações podem ser encontradas aqui

Devpool
fonte
16

EDIT : Esta resposta (e a maioria das outras) são obsoletas; veja a resposta de Devpool .


Originalmente, não havia opções de configuração para tornar " git diff --ignore-submodules" e " git status --ignore-submodules" o padrão global (mas consulte também Configurando sinalizadores padrão do git nos comandos ). Uma alternativa é definir uma ignoreopção de configuração padrão em cada sub-módulo individual que você deseja ignorar (para ambos git diffe git status), no .git/configarquivo (somente local) ou .gitmodules(será versionado pelo git). Por exemplo:

[submodule "foobar"]
    url = [email protected]:foo/bar.git
    ignore = untracked

ignore = untrackedignorar apenas arquivos não rastreados, ignore = dirtytambém ignorar arquivos modificados e ignore = allignorar também confirma. Aparentemente, não há como curinga para todos os submódulos.

Ralph Versteegen
fonte
13

Esse é o caso, porque o ponteiro que você possui para o submódulo não é o que realmente está no diretório do submódulo. Para corrigir isso, você deve executar git submodule updatenovamente:

Robin Ren
fonte
9
git submodule foreach --recursive git checkout .

Isso não funcionou para mim, mas me deu uma lista de arquivos (no meu caso, apenas um) que foram alterados no submódulo (sem eu fazer nada lá).

Então, eu poderia ir para o submodule e o status do git me mostrou que meu HEAD estava desconectado -> git checkout master, git status para ver o arquivo modificado mais uma vez, git checkout> filename <, git pull e tudo bem novamente.

Só um pouco
fonte
9

Acabei removendo o diretório do submódulo e inicializando-o novamente

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update
Szymon Wygnański
fonte
4
Eu prefiro entender o que aconteceu, mas isso também era a única coisa que funcionou para mim ...
smilebomb
6

Um submódulo pode ser marcado como sujo se as configurações do modo de arquivo estiverem ativadas e você tiver alterado as permissões de arquivo na subárvore do submódulo.

Para desativar o modo de arquivo em um submódulo, você pode editar /.git/modules/path/to/your/submodule/config e adicionar

[core]
  filemode = false

Se você deseja ignorar todos os estados sujos, pode definir a ignore = dirtypropriedade no arquivo /.gitmodules , mas acho melhor desativar apenas o modo de arquivo.

dryobs
fonte