Apesar do GIT NÃO armazenar deltas de arquivo, você ainda pode reverter para versões de arquivo anteriores (tempo ilimitado?)


14

Eu li que o Git não armazena deltas de arquivos. Se isso for verdade, como ele suporta a reversão de arquivo para versões anteriores? Se estiver armazenando o arquivo inteiro, o espaço do repositório no disco deverá aumentar para ser incontrolavelmente grande. O Git suporta reversões e diferenças de arquivos para a versão 1 do arquivo? Ele ainda suporta um conceito de versão relacionado a arquivos? Isto é (acredito) essencial para a minha compreensão de um VCS / DVCS e minhas necessidades. Preciso comparar o que estou prestes a fazer check-in com as versões anteriores.

Respostas:


44

O Git não descarta informações por si só *. Todas as versões anteriores de todos os arquivos estão sempre disponíveis para reversões, diferenças, inspeções etc.

Árvore inteira versus arquivos individuais

O que você pode estar tentando reconciliar é a idéia de acessar uma versão antiga de um arquivo individual versus o fato de o modelo de histórico do Git estar focado em toda a árvore. O controle de versão de árvore inteira exige um pouco mais de trabalho para ver (por exemplo) a versão foo.ccomo ela existia foo.chá dez alterações atrás, e dez alterações de árvore inteira atrás:

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

Os benefícios da orientação em árvore, principalmente a capacidade de visualizar os commits como uma unidade de alterações interdependentes feitas em várias partes da árvore, geralmente superam em muito a digitação extra (que pode ser aliviada com aliases, scripts etc.) e o tempo da CPU gasto cavando através de confirmações passadas.

Eficiência de armazenamento

Quando um novo objeto (por exemplo, um arquivo com conteúdo não visto anteriormente) entra no sistema, ele é armazenado com compressão simples (zlib) como um “objeto solto”. Quando objetos soltos suficientes se acumulam (com base na gc.autoopção de configuração; ou quando o usuário executa o git gc ou um dos comandos de compactação de nível inferior), o Git coleta muitos objetos soltos em um único "arquivo de pacote".

Os objetos em um arquivo de pacote podem ser armazenados como dados compactados simples (o mesmo que um objeto solto, apenas empacotado com outros objetos) ou como deltas compactados em relação a outro objeto. Os deltas podem ser encadeados em profundidades configuráveis ​​( pack.depth) e podem ser criados contra qualquer objeto adequado ( pack.windowcontrola a extensão em que o Git pesquisa a melhor base delta; uma versão de um arquivo historicamente não relacionado pode ser usada como base, se isso produzir um boa compactação delta). A latitude que as configurações de profundidade e tamanho da janela fornecem ao mecanismo de compactação delta geralmente resulta em uma compactação delta melhor do que na compactação "diff" simples de uma versão contra a próxima / versão anterior no estilo CVS.

É essa compactação delta agressiva (combinada com a compactação zlib normal) que geralmente permite que um repositório Git (com histórico completo e uma árvore de trabalho descompactada) ocupe menos espaço que um único check-out de SVN (com árvore de trabalho descompactada e cópia intocada).

Veja as seções Como o Git armazena objetos e O arquivo de pacotes do The Git Community Book . Também a página de manual git pack-objects .

* Você pode dizer ao Git que joga fora os commits “reescrevendo o histórico” e com comandos como git reset , mas mesmo nesses casos o Git “agarra” os recém-descartados por um tempo, apenas no caso de você decidir que precisa deles. Veja git reflog e git ameixa .


3
+1 apenas pela quantidade e detalhes das informações que você forneceu.
Tamara Wijsman

3
Além disso, como o Git usa instantâneos de arquivos em vez de deltas, voltar um longo caminho na história é realmente mais fácil. Imagine que você precisa ver um arquivo de 20 confirmações atrás. Com deltas, você precisa desfazer 20 conjuntos de alterações; com instantâneos, você apenas pega o instantâneo certo. Quanto maior o seu histórico, maior a vantagem. E se você quiser ver a comparação entre a versão atual e que um, é apenas uma única diff, em vez de ter de decidir o que tem sido feito, desfeito, refeito, etc.
Nathan Long

Chris, você parece ter uma boa noção dos aspectos internos do Git. Alguma chance de você dar uma guinada nisso? stackoverflow.com/questions/5176225/...
Nathan Long

@ ChrisJohnsen Por favor me ajude a entender isso. Com base no que você disse, o Git pode obter eficiência de armazenamento semelhante (ou melhor) que o Subversion? Sei que se eu confirmar um arquivo com poucas alterações várias vezes, um valor de 1 GB poderá ser salvo em 100 MB. O Git pode fazer o mesmo?
Alireza Noori 12/02/2013

@AlirezaNoori: Tudo depende da natureza dos dados e das alterações capturadas (tamanho do arquivo, compressibilidade do arquivo, tamanho e localização das alterações, etc.). Algo assim certamente deve ser possível (dependendo das especificidades). Em geral, os arquivos de pacote do Git podem ser extraídos de uma seleção maior de bases para sua compactação delta, em comparação com os deltas estritamente cronológicos reversos que os servidores SVN usam (usado? Eu não sigo o desenvolvimento do SVN…). Se você tiver alguma pergunta específica em mente, considere fazer uma nova pergunta que inclua todos os detalhes pertinentes.
31813 Chris Johnsen

1

Pode ser lido na mesma página:

...

Consequentemente, o Git não registra explicitamente os relacionamentos de revisão de arquivos em nenhum nível abaixo da árvore do código-fonte.

...

É um pouco mais caro examinar o histórico de alterações de um único arquivo do que todo o projeto. Para obter um histórico de alterações que afetam um determinado arquivo, o Git deve percorrer o histórico global e determinar se cada alteração modificou esse arquivo. Esse método de examinar o histórico, no entanto, permite ao Git produzir com igual eficiência um único histórico, mostrando as alterações em um conjunto arbitrário de arquivos. Por exemplo, um subdiretório da árvore de origem mais um arquivo de cabeçalho global associado é um caso muito comum.

...

Assim, você pode voltar às revisões anteriores de um arquivo e comparar dois arquivos.


1

De fato, o git salva deltas de arquivos, mas os salva como delta de toda a árvore de arquivos.

Para ver as diferenças entre as versões, siga um destes procedimentos:

  1. git diff - mostra as diferenças entre a última versão registrada e os arquivos que foram alterados, mas que não foram git addexecutados neles.
  2. git diff --cached - mostra as diferenças entre a versão anterior e o que todos os arquivos foram git addexecutados, mas não foram confirmados
  3. git diff commitid - mostra as diferenças entre o diretório de trabalho atual e um commit anterior, conforme especificado com o commitid
  4. git diff commita..commitb - mostra as diferenças entre dois commits, a e b. Os commits também podem ser nomes simbólicos como ramificações ou tags.

Esta resposta não está realmente correta. Todos esses comandos podem ser aplicados a um conjunto arbitrário de arquivos, bem como toda a árvore - basta adicionar os nomes de arquivo no final ...
naught101
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.