Nonostante GIT NON memorizzi i delta dei file, è ancora possibile ripristinare le versioni precedenti dei file (tempi illimitati?)


14

Ho letto che Git non memorizza i delta dei file. Se questo è vero, come supporta il rollback dei file alle versioni precedenti? Se sta memorizzando l'intero file, lo spazio del repository su disco deve aumentare in modo ingestibile. Git supporta il rollback dei file e le differenze alla versione 1 del file? Supporta anche un concetto di versioning relativo ai file? Questo è (credo) essenziale per la mia comprensione di un VCS / DVCS e delle mie esigenze. Devo essere in grado di confrontare ciò che sto per verificare con le versioni precedenti.

Risposte:


44

Git non elimina le informazioni da solo *. Tutte le versioni precedenti di ogni file sono sempre disponibili per ripristini, differenze, ispezioni, ecc.

Intero albero contro singoli file

Quello che potresti provare a conciliare è l'idea di accedere a una vecchia versione di un singolo file rispetto al fatto che il modello di cronologia di Git è focalizzato sull'intero albero. Il versioning dell'intero albero richiede un po 'più di lavoro per vedere (per esempio) la versione di foo.ccome esisteva dieci foo.ccambiamenti fa contro dieci cambiamenti dell'albero intero:

# 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

I vantaggi dell'orientamento dell'albero, principalmente la capacità di visualizzare i commit come unità di modifiche interdipendenti apportate a varie parti dell'intero albero, in generale superano di gran lunga la digitazione aggiuntiva (che può essere alleviata con alias, script, ecc.) E tempo della CPU trascorso a scavare in impegni passati.

Efficienza di archiviazione

Quando un nuovo oggetto (ad esempio un file con contenuti mai visti prima) entra nel sistema, viene archiviato con una semplice compressione (zlib) come "oggetto sciolto". Quando si accumulano abbastanza oggetti sfusi (in base gc.autoall'opzione di configurazione; o quando l'utente esegue git gc o uno dei comandi di impacchettamento di livello inferiore), Git raccoglierà molti oggetti sfusi in un unico "file pack".

Gli oggetti in un file pack possono essere archiviati come semplici dati compressi (lo stesso di un oggetto sciolto, semplicemente impacchettato con altri oggetti) o come delta compressi rispetto ad altri oggetti. I delta possono essere concatenati a profondità configurabili ( pack.depth) e possono essere fatti contro qualsiasi oggetto adatto ( pack.windowcontrolla quanto Git cerca la migliore base di delta; una versione di un file storicamente non correlato può essere usata come base se ciò comporterebbe un buona compressione delta). La latitudine che le configurazioni di profondità e dimensione della finestra offrono al motore di compressione delta spesso si traduce in una migliore compressione delta rispetto alla semplice compressione “diff” di una versione-CV-contro-la / successiva-versione precedente.

È questa compressione delta aggressiva (combinata con la normale compressione zlib) che spesso può consentire a un repository Git (con cronologia completa e un albero di lavoro non compresso) di occupare meno spazio di un singolo checkout SVN (con albero di lavoro non compresso e copia originale).

Vedi le sezioni Come Git memorizza oggetti e The Packfile del libro della community di Git . Anche la manpage git pack-objects .

* Puoi dire a Git di eliminare i commit "riscrivendo la cronologia" e con comandi come git reset , ma anche in questi casi Git "si blocca" sui commit appena scartati per un po ', nel caso in cui decidi di averne bisogno. Vedi git reflog e git prune .


3
+1 solo per la quantità e il dettaglio delle informazioni fornite.
Tamara Wijsman,

3
Inoltre, poiché Git utilizza istantanee di file anziché delta, tornare indietro nella storia è in realtà più semplice. Immagina di dover vedere un file di 20 commit fa. Con delta, devi annullare 20 changeset; con le istantanee, basta catturare l'istantanea giusta. Più lunga è la tua storia, maggiore è il vantaggio. E se vuoi vedere la differenza tra la versione corrente e quella, è solo una differenza, piuttosto che dover decidere cosa è stato fatto, annullato, rifatto, ecc.
Nathan Long,

Chris, sembra che tu abbia una buona padronanza degli interni di Git. Qualche possibilità che tu possa fare un salto in questo? stackoverflow.com/questions/5176225/…
Nathan Long

@ChrisJohnsen Per favore aiutami a capire questo. Sulla base di ciò che hai detto, Git può ottenere un'efficienza di archiviazione simile (o migliore) rispetto a Subversion? So che se commetto un file con piccole modifiche numerose volte, è possibile salvare dati da 1 GB in 100 MB. Git può fare lo stesso?
Alireza Noori,

@AlirezaNoori: tutto dipende dalla natura dei dati e dalle modifiche acquisite (dimensione del file, comprimibilità del file, dimensione e posizione delle modifiche, ecc.). Qualcosa del genere dovrebbe certamente essere possibile (a seconda delle specifiche). In generale, i file pack di Git possono attingere da una più ampia selezione di basi per la sua compressione delta rispetto ai delta strettamente cronologici inversi che usano i server SVN (usato? Non seguo lo sviluppo SVN ...). Se hai in mente qualche domanda specifica, dovresti considerare di porre una nuova domanda che includa tutti i dettagli pertinenti.
Chris Johnsen,

1

Può essere letto sulla stessa pagina:

...

Di conseguenza, Git non registra esplicitamente le relazioni di revisione dei file a nessun livello al di sotto della struttura del codice sorgente.

...

È leggermente più costoso esaminare la cronologia delle modifiche di un singolo file rispetto all'intero progetto. Per ottenere una cronologia delle modifiche che interessano un determinato file, Git deve seguire la cronologia globale e quindi determinare se ogni modifica ha modificato quel file. Questo metodo di esame della cronologia, tuttavia, consente a Git di produrre con uguale efficienza una singola cronologia che mostra le modifiche a un set arbitrario di file. Ad esempio, una sottodirectory dell'albero di origine più un file di intestazione globale associato è un caso molto comune.

...

Quindi puoi tornare alle revisioni precedenti di un file e confrontare due file.


1

git infatti salva delta di file, ma li salva come delta dell'intero albero di file.

Per vedere le differenze tra le versioni, effettuare una delle seguenti operazioni:

  1. git diff - mostra le differenze tra l'ultima versione archiviata e i file che sono stati modificati, ma non git addeseguiti su di essi.
  2. git diff --cached - mostra le differenze tra la versione precedente e ciò che tutti i file che erano stati git addeseguiti, ma non sono stati sottoposti a commit
  3. git diff commit - mostra le differenze tra la directory di lavoro corrente e un commit precedente come specificato con il commit
  4. git diff commita..commitb - mostra le differenze tra due commit, a e b. I commit potrebbero anche essere nomi simbolici come rami o tag.

Questa risposta non è proprio corretta. Tutti questi comandi possono essere applicati a un insieme arbitrario di file e all'intero albero - basta aggiungere i nomi dei file alla fine ...
nought101
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.