Eu tenho um repositório Git com muitos commits que não estão sob nenhuma ramificação específica, eu posso git show
, mas quando tento listar as ramificações que os contêm, ele não informa nada.
Eu pensei que este é o problema de commit / tree pendente (como resultado da ramificação -D), então eu removi o repo, mas ainda vejo o mesmo comportamento depois disso:
$ git fetch origin
$ git fsck --unreachable
$ git fsck
Sem saída, nada pendente (certo?). Mas o commit existe
$ git show 793db7f272ba4bbdd1e32f14410a52a412667042
commit 793db7f272ba4bbdd1e32f14410a52a412667042
Author: ...
e não é alcançável através de nenhum ramo como
$ git branch --contains 793db7f272ba4bbdd1e32f14410a52a412667042
não dá saída.
Qual é exatamente o estado desse commit? Como posso listar todos os commits em um estado semelhante? Como posso excluir confirmações como essas?
git
branch
git-dangling
Samer Buna
fonte
fonte
Respostas:
Observe que as confirmações referidas no seu reflog são consideradas acessíveis.
Passe
--no-reflogs
para convencergit fsck
a mostrá-los a você.Depois que suas entradas de reflog expirarem, esses objetos também serão limpos
git gc
.A expiração é regulada pelo
gc.pruneexpire
,gc.reflogexpire
egc.reflogexpireunreachable
configurações. Cf.git help config
.Os padrões são todos bastante razoáveis.
fonte
git help glossary
define dessa maneira ... enquanto sua definição de "alcançável" não é reduzida dessa maneira, por isso são contraditórias. Engraçado - então o que eu disse é realmente consistente com a confusão emgitglossary
... Não são os conceitos que são confusos, apenas a terminologia. O ponto é que os compromissos "pendentes" são aqueles que nada mais aponta. Ajudaria se eu digo “reflogs para outra forma commits inacessível” ...?master
, você fazgit commit
e recebe um commit000001
. Então você fazgit commit --amend
, o que lhe dá confirmação000002
. Não há mais tags ou ramificações apontando para000001
você, e você não pode vê-lo em seu log sem a--reflog
opção, mas se desejar, ainda poderá acessá-logit checkout 000001
. Agora, a pergunta é:000001
um commit pendente , ou um commit inacessível , ou nenhum, ou ambos?Para remover todos os commits dangling e aqueles alcançáveis dos reflogs, faça o seguinte:
Mas esteja certo de que é isso que você deseja. Eu recomendo que você leia as páginas de manual, mas aqui está a essência:
git gc
remove objetos inacessíveis (confirmações, árvores, blobs (arquivos)). Um objeto está inacessível se não faz parte do histórico de algum ramo. Na verdade, é um pouco mais complicado:git gc
faz algumas outras coisas, mas elas não são relevantes aqui e não são perigosas.Objetos inacessíveis com menos de duas semanas não são removidos, portanto, usamos
--prune=now
que significa "remover objetos inacessíveis que foram criados antes agora".Os objetos também podem ser alcançados através do reflog. Enquanto os ramos registram o histórico de alguns projetos, os reflogs registram o histórico desses ramos. Se você alterar, redefinir etc. as confirmações serão removidas do histórico da ramificação, mas o git as manterá por perto caso você perceba que cometeu um erro. Os registros são uma maneira conveniente de descobrir quais operações destrutivas (e outras) foram executadas em uma ramificação (ou HEAD), facilitando a destruição de uma operação destrutiva.
Portanto, também precisamos remover os reflogs para remover tudo o que não é acessível a partir de um ramo. Fazemos isso expirando
--all
reflogs. Novamente, o git mantém um pouco dos reflogs para proteger os usuários, então, novamente, temos que dizer para não fazer isso:--expire-unreachable=now
.Como eu uso principalmente o reflog para me recuperar de operações destrutivas, costumo usá-lo
--expire=now
, o que reduz completamente os reflexos.fonte
git reflog expire --expire-unreachable=now --all
derruba todos os seus esconderijos!Eu tive o mesmo problema, ainda depois de seguir todos os conselhos deste tópico:
Se não é um reflog e não um ramo, ... deve ser uma tag !
Removai as tags
git tag -d <tagname>
e refiz a limpeza, e os commits antigos haviam desaparecido.fonte
provavelmente só precisa ser
para também informar sobre ramificações de controles remotos
fonte
git push -d origin next
não ajuda.git fetch --prune
fez o truque. mas em todas as respostas, estou faltando uma verificação de tags que fazem referência a esse commit. Ainda não sei como verificar as tags com uma confirmação (removi todas).git fsck --unreachable
está realmente se comunicando através da rede com a remota para descobrir quais confirmações são alcançáveis?git fsck --unreachable
não precisa se comunicar pela rede com o controle remoto para descobrir quais ramificações remotas contêm quais confirmações. As informações da filial remota são armazenadas localmente, em, por exemplo,.git/refs/remotes/origin
(ou empacked-refs
).Eu tive uma questão semelhante. Eu corri
git branch --contains <commit>
e ele não retornou nenhuma saída, como na pergunta.Mas mesmo depois de correr
meu commit ainda estava acessível usando
git show <commit>
. Isso ocorreu porque um dos commits em seu "branch" desanexado / danificado foi marcado. Tirei a etiqueta, executei os comandos acima novamente e fiquei com o ouro.git show <commit>
retornoufatal: bad object <commit>
- exatamente o que eu precisava. Espero que isso ajude alguém que estava tão preso quanto eu.fonte
Acidentalmente, acertei a mesma situação e constatei que meus stashes contêm referência ao commit inacessível e, portanto, o commit presumível inacessível estava acessível a partir dos stashes.
Foi isso que eu fiz para torná-lo verdadeiramente inacessível.
fonte
git gc --prune=<date>
o padrão é remover objetos com mais de duas semanas atrás. Você pode definir uma data mais recente. Porém, os comandos git que criam objetos soltos geralmente executam git gc --auto (que remove objetos soltos se seu número exceder o valor da variável de configuração gc.auto).Tem certeza de que deseja excluir essas confirmações? A configuração padrão do gc.auto garantirá que os objetos soltos não ocupem uma quantidade razoável de memória, e armazenar objetos soltos por um certo período de tempo geralmente é uma boa idéia. Dessa forma, se você perceber amanhã que seu ramo excluído continha uma confirmação necessária, poderá recuperá-lo.
fonte