Eu me sinto como uma criança no escritório do diretor explicando que o cachorro comeu minha lição de casa na noite anterior, mas estou encarando um bug louco de perda de dados e não consigo descobrir como isso aconteceu. Gostaria de saber como o git pode comer todo o meu repositório! Eu coloquei o git no espremedor muitas vezes e ele nunca piscou. Eu usei para dividir um repositório de 20 Gig Subversion em 27 repositórios Git e ramifiquei o foo deles para desembaraçar a bagunça e isso nunca perdeu um byte para mim. O reflog está sempre lá para recorrer. Desta vez, o tapete se foi!
Da minha perspectiva, tudo o que fiz foi executar git pull
e desarticulou meu repositório local inteiro. Não quero dizer que "estraguei a versão com check-out" ou "o ramo em que eu estava" ou algo assim. Quero dizer que a coisa toda se foi .
Aqui está uma captura de tela do meu terminal no incidente:
Deixe-me levá-lo através disso. Meu prompt de comando inclui dados sobre o atual repositório git (usando a implementação vcs_info do prezto) para que você possa ver quando o repositório git desapareceu. O primeiro comando é bastante normal:
» caleb » jaguar » ~/p/w/incil.info » ◼ zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
Lá você pode ver que eu estava no ramo 'zend' e fiz check-out do mestre. Por enquanto, tudo bem. Você verá no prompt antes do meu próximo comando que ele alternou com êxito as ramificações:
» caleb » jaguar » ~/p/w/incil.info » ◼ master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
+ 7412a21...eca4d26 master -> origin/master (forced update)
f03fa5d..c8ea00b devel -> origin/devel
+ 2af282c...009b8ec verse-spinner -> origin/verse-spinner (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s
E assim acabou. O marcador de tempo decorrido é emitido antes do próximo prompt, se tiverem passado mais de 10 segundos. O Git não deu nenhuma saída além do aviso de que estava rebobinando para reproduzir. Nenhuma indicação de que terminou.
O próximo prompt não inclui dados sobre o ramo em que estamos ou o estado do git.
Sem perceber que havia falhado, tentei, inconscientemente, executar outro comando git apenas para saber que não estava em um repositório git. Observe que o PWD não mudou:
» caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).
Depois disso, uma olhada ao redor mostrou que eu estava em um diretório completamente vazio. Nada. Nenhum diretório '.git', nada. Esvaziar.
Meu git local está na versão 2.0.2. Aqui estão alguns petiscos da minha configuração do git que podem ser relevantes para entender o que aconteceu:
[branch]
autosetuprebase = always
rebase = preserve
[pull]
rebase = true
[rebase]
autosquash = true
autostash = true
[alias]
co = checkout
Por exemplo, eu git pull
configurei para sempre fazer uma rebase em vez de uma mesclagem, para que parte da saída acima seja normal.
Eu posso recuperar os dados. Acho que não havia outros objetos git além de stash sem importância que não foram enviados para outros repositórios, mas eu gostaria de saber o que aconteceu .
Eu verifiquei:
- Mensagens no dmesg ou no diário systemd. Nada nem remotamente relevante.
- Não há indicação de falha na unidade ou no sistema de arquivos (LVM + LUKS + EXT4 parecem normais). Não há nada em perdido + encontrado.
- Eu não corri mais nada. Não há nada na história que não esteja mostrando acima e nenhum outro terminal foi usado durante esse período. Não há
rm
comandos flutuando que possam ter sido executados no CWD errado, etc. - Picar em outro repositório git em outro diretório não mostra nenhuma anormalidade aparente executando
git pull
s.
O que mais eu deveria estar procurando aqui?
fonte
.git
não existe. Nada funciona - o que costumava ser o diretório raiz do git não tem nada.Respostas:
Sim,
git
comi minha lição de casa. Tudo isso.Fiz uma
dd
imagem desse disco após o incidente e brinquei com ele mais tarde. Reconstruindo a série de eventos dos logs do sistema, deduzo o que aconteceu foi algo como isto:pacman -Syu
) foi emitido dias antes deste incidente.git checkout
e antes dagit pull
.git
binário foi substituído após ogit pull
início e antes de terminar.git
descansou de todos os seus trabalhos. E deletou o mundo para que todos os outros também descansassem.Não sei exatamente qual condição de corrida ocorreu que fez isso acontecer, mas trocar binários no meio de uma operação certamente não é bom nem uma condição testável / repetível. Normalmente, uma cópia de um binário em execução é armazenada na memória, mas
git
é estranha e algo sobre o modo como gera versões de si mesma, eu tenho certeza que levou a essa bagunça. Obviamente, deveria ter morrido em vez de destruir tudo, mas foi o que aconteceu.fonte
git-fetch
,git-rebase
ougit-merge
egit gc
Possivelmente, ao definir o caminho do arquivo a ser excluído.
Seu caso me lembrou um belo dia em que, quando meu
remove(path)
método caseiro tentou remover a pasta raiz, porque o parâmetro fornecido era uma string vazia que o SO corrigiu (!) Como pasta raiz.Este pode ser um bug semelhante do git. De tal modo que:
remove(project_folder + file_path)
(pseudo-código)file_path
estava vazio na época.remove(project_folder)
fonte
Com sorte, você pode corrigir isso com o seguinte comando:
Quando possíveis alterações perigosas começam, o git armazena seu estado atual em ORIG_HEAD. Com ele, você pode desfazer uma mesclagem ou rebase.
Git Manual: Desfazendo uma Mesclagem
fonte
Parece que alguém executou
git push --force
esse repositório e você efetuou essas alterações. Tente clonar o repositório novamente, para que você volte a um estado de funcionamento limpo novamente.fonte
.git
diretório com um empurrão forçado