A exclusão de uma ramificação no git a remove do histórico?

189

Vindo do svn, apenas começando a se familiarizar com o git.

Quando um ramo é excluído no git, ele é removido do histórico?

No svn, você pode recuperar facilmente uma ramificação revertendo a operação de exclusão (mesclagem reversa). Como todas as exclusões no svn, o ramo nunca é realmente excluído, apenas é removido da árvore atual.

Se o ramo for realmente excluído do histórico no git, o que acontece com as alterações que foram mescladas nesse ramo? Eles são mantidos?

Ken Liu
fonte

Respostas:

249

Ramos são apenas indicadores de commit no git. No git, cada commit tem uma árvore de código-fonte completa, é uma estrutura muito diferente do svn, onde todos os ramos e tags (por convenção) vivem em 'pastas' separadas do repositório, ao lado do 'tronco' especial.

Se a ramificação foi mesclada em outra ramificação antes de ser excluída, todas as confirmações ainda estarão acessíveis na outra ramificação quando a primeira ramificação for excluída. Eles permanecem exatamente como eram.

Se o ramo for excluído sem ser mesclado em outro ramo, as confirmações nesse ramo (até o ponto em que o bifurcado de uma confirmação ainda acessível) deixará de ser visível.

As confirmações ainda serão mantidas no repositório e é possível recuperá-las imediatamente após a exclusão, mas eventualmente elas serão coletadas como lixo.

CB Bailey
fonte
3
Obrigado pela resposta. Você poderia esclarecer o que quer dizer com "cada confirmação tem uma árvore de código-fonte completa"? Pelo que entendi, cada confirmação no git é um conjunto de deltas que se referem a uma confirmação pai, não a uma árvore inteira.
Ken Liu
2
@ Ken Liu: Uma confirmação contém ponteiros para zero ou mais confirmações pai, um objeto de árvore e alguns metadados sobre a confirmação. A confirmação, portanto, identifica exclusivamente uma árvore de origem de casal e, quando visualizada em relação aos pais, as alterações que introduziu.
CB Bailey
9
@ Ken Liu: Depende exatamente do que você esteve por 'conter', mas sim, essencialmente cada confirmação contém uma árvore completa. No banco de dados de objetos, os objetos são indexados por id, de modo que os objetos sejam compartilhados entre todos os objetos (árvores e confirmações) que os referenciam, para que a sobrecarga implícita de armazenamento não seja tão ruim quanto parece inicialmente. O git também possui uma otimização de armazenamento eficiente (arquivos de pacote), que tornam o uso ainda mais eficiente do espaço em disco.
CB Bailey
22
"eventualmente eles serão coletados de lixo" - Eventualmente, quando?
BadHorsie
7
@BadHorsie, depende .
ALIOLI
86

No Git, ramificações são apenas ponteiros (referências) para confirmações em um gráfico acíclico direcionado (DAG) de confirmações. Isso significa que a exclusão de uma ramificação remove apenas referências a confirmações, o que pode tornar algumas confirmações no DAG inacessíveis, invisíveis. Mas todas as confirmações que estavam em uma ramificação excluída ainda estariam no repositório, pelo menos até que as confirmações inacessíveis sejam removidas (por exemplo, usandogit gc ).

Observe que git branch -dse recusaria a excluir uma ramificação se não tiver certeza de que a exclusão não deixaria confirmações inacessíveis. Você precisa usar o mais fortegit branch -D para forçar a exclusão de uma ramificação, se ela puder deixar confirmações inacessíveis.

Observe também que confirmações inacessíveis, se estiverem presentes, são apenas aquelas confirmadas entre a última dica de uma ramificação excluída e uma confirmação que foi mesclada com outra ramificação existente, qualquer confirmação marcada ou o ponto de ramificação; o que for mais tarde. Por exemplo, na seguinte situação:

---- O ---- * ---- * ---- / M ---- * <- mestre <- CABEÇA
     \ /
      \ --. ---- .-- / - x --- y <- ramificação excluída

somente confirma 'x' e 'y' se tornam inacessíveis após a exclusão da ramificação.

Se você operasse em uma ramificação excluída dentro do gc.reflogExpireperíodo, padrão 90 dias, você teria a última dica de uma ramificação excluída registrada no reflog HEAD (consulte git reflog show HEADou git log --oneline --walk-reflogs HEAD). Você poderá usar o reflog HEAD para recuperar o ponteiro excluído. Observe também que, nesse caso, confirmações inacessíveis em apenas uma ramificação excluída estariam protegidas contra remoção (remoção) dentro do gc.reflogExpireUnreachableperíodo, que por padrão é de 30 dias.

Se você não conseguir encontrar a ponta de uma ramificação excluída no reflog para HEAD, tente usar git fscka opção "consolidação inacessível <sha1>" e examine-as (via git show <sha1>ou git log <sha1>) para encontrar a ponta da ramificação excluída.

Independentemente de como você encontra a ponta de uma ramificação excluída, você pode desfazer a exclusão ou, em vez disso, recriar uma ramificação excluída usando

git branch <deleted-branch> <found-sha1-id>

Observe, no entanto, que o reflog para uma ramificação seria perdido.


Há também o script git-resurrect.sh, no contrib/qual ajuda a encontrar vestígios de uma dica de ramificação com nome determinado e a ressuscitá-la (cancelar a exclusão).

Jakub Narębski
fonte
1
Impressionante! git reflog show HEADlistei o commit e criei um novo ramo, como você disse, perfeito.
Steven Almeroth
2

Se você estiver preocupado com filiais excluídas acidentalmente e não tiver mais uma cópia local de seu repositório, existem extensões para servidores Git corporativos como o Gerrit que detectam reescrições de histórico e exclusões de filiais, fazendo o backup com uma ref especial para que pode ser restaurado, se necessário, e não será podado pela coleta de lixo. Os administradores da Gerrit ainda podem remover confirmações selecionadas, se necessário por motivos legais.

Johanned Nicolai
fonte