Malgré le fait que GIT ne stocke PAS les deltas de fichiers, pouvez-vous toujours revenir aux versions de fichiers précédentes (temps illimité?)


14

J'ai lu que Git ne stocke pas les deltas de fichiers. Si cela est vrai, comment prend-il en charge la restauration des fichiers vers les versions précédentes? S'il stocke l'intégralité du fichier, l'espace du référentiel sur le disque doit devenir de manière ingérable. Git prend-il en charge les annulations de fichiers et les différences avec la version de fichier 1? Soutient-il même un concept de versioning lié aux fichiers? C'est (je crois) essentiel à ma compréhension d'un VCS / DVCS et de mes besoins. Je dois pouvoir comparer ce que je suis sur le point de vérifier avec les versions précédentes.

Réponses:


44

Git ne jette pas d'informations par lui-même *. Toutes les versions précédentes de chaque fichier sont toujours disponibles pour les révisions, les différences, les inspections, etc.

Arborescence complète versus fichiers individuels

Ce que vous essayez peut-être de réconcilier, c'est l'idée d'accéder à une ancienne version d'un fichier individuel par rapport au fait que le modèle d'historique de Git se concentre sur l'ensemble de l'arborescence. Le versionnage d'arbre entier nécessite un peu plus de travail pour voir (par exemple) la version foo.ctelle qu'elle existait il y a dix foo.cchangements par rapport à dix changements d'arbre entier:

# 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

Les avantages de l'orientation arborescente, principalement la possibilité de visualiser les validations comme une unité de modifications interdépendantes apportées à diverses parties de l'arbre entier, l'emportent largement sur la saisie supplémentaire (qui peut être atténuée avec des alias, des scripts, etc.) et le temps CPU passé à fouiller dans les commits passés.

Efficacité de stockage

Lorsqu'un nouvel objet (par exemple un fichier avec un contenu précédemment invisible) entre dans le système, il est stocké avec une compression simple (zlib) en tant qu '«objet lâche». Lorsque suffisamment d'objets en vrac s'accumulent (en fonction de l' gc.autooption de configuration; ou lorsque l'utilisateur exécute git gc ou l'une des commandes d'emballage de niveau inférieur), Git collectera de nombreux objets en vrac dans un seul "fichier de pack".

Les objets d'un fichier pack peuvent être stockés sous forme de données compressées simples (identiques à un objet lâche, simplement regroupées avec d'autres objets) ou sous forme de deltas compressés contre un autre objet. Les deltas peuvent être enchaînés ensemble à des profondeurs configurables ( pack.depth) et peuvent être créés par rapport à n'importe quel objet approprié ( pack.windowcontrôle l'étendue de la recherche par Git de la meilleure base delta; une version d'un fichier historiquement indépendant peut être utilisée comme base si cela produirait un bonne compression delta). La latitude que confèrent les configurations de profondeur et de taille de fenêtre au moteur de compression delta se traduit souvent par une meilleure compression delta que la compression simple «diff» d'une version contre la version suivante / précédente de style CVS.

C'est cette compression delta agressive (combinée à la compression zlib normale) qui peut souvent laisser un référentiel Git (avec l'historique complet et une arborescence de travail non compressée) prendre moins d'espace qu'une seule extraction SVN (avec une arborescence de travail non compressée et une copie vierge).

Voir les sections Comment Git stocke les objets et Les sections Packfile du Git Community Book . Également la page de manuel git pack-objects .

* Vous pouvez dire à Git de supprimer les commits en «réécrivant l'historique» et avec des commandes comme git reset , mais même dans ces cas, Git «s'accroche» aux commits nouvellement supprimés pendant un certain temps, juste au cas où vous décideriez que vous en avez besoin. Voir git reflog et git prune .


3
+1 uniquement pour la quantité et le détail des informations que vous avez fournies.
Tamara Wijsman

3
De plus, comme Git utilise des instantanés de fichiers plutôt que des deltas, remonter dans le temps est en fait plus facile. Imaginez que vous ayez besoin de voir un fichier d'il y a 20 commits. Avec les deltas, vous devez annuler 20 changesets; avec des instantanés, il vous suffit de saisir le bon instantané. Plus votre historique est long, plus l'avantage est grand. Et si vous voulez voir le diff entre la version actuelle et celle-ci, ce n'est qu'un seul diff, plutôt que d'avoir à décider ce qui a été fait, défait, refait, etc.
Nathan Long

Chris, vous semblez avoir une assez bonne maîtrise des composants internes de Git. Y a-t-il une chance que vous preniez un élan à cela? stackoverflow.com/questions/5176225/…
Nathan Long

@ChrisJohnsen Veuillez m'aider à comprendre cela. D'après ce que vous avez dit, Git peut-il obtenir une efficacité de stockage similaire (ou meilleure) que Subversion? Je sais que si je valide plusieurs fois un fichier avec de petits changements, 1 Go de données peut être enregistré dans 100 Mo. Git peut-il faire de même?
Alireza Noori

@AlirezaNoori: Tout dépend de la nature des données et des changements capturés (taille du fichier, compressibilité du fichier, taille et emplacement des changements, etc.). Quelque chose comme ça devrait certainement être possible (selon les spécificités). En général, les fichiers pack de Git peuvent puiser dans une plus grande sélection de bases pour sa compression delta par rapport aux deltas strictement chronologiques inverses que les serveurs SVN utilisent (utilisés? Je ne suis pas le développement SVN…). Si vous avez une question précise en tête, vous devriez envisager de poser une nouvelle question qui comprend tous les détails pertinents.
Chris Johnsen

1

Il peut être lu sur la même page:

...

Par conséquent, Git n'enregistre pas explicitement les relations de révision de fichier à aucun niveau en dessous de l'arborescence du code source.

...

Il est légèrement plus coûteux d'examiner l'historique des modifications d'un seul fichier que l'ensemble du projet. Pour obtenir un historique des modifications affectant un fichier donné, Git doit parcourir l'historique global, puis déterminer si chaque modification a modifié ce fichier. Cette méthode d'examen de l'historique permet cependant à Git de produire avec une efficacité égale un historique unique montrant les modifications apportées à un ensemble arbitraire de fichiers. Par exemple, un sous-répertoire de l'arborescence source plus un fichier d'en-tête global associé est un cas très courant.

...

Ainsi, vous pouvez revenir aux révisions précédentes d'un fichier et comparer deux fichiers.


1

git enregistre en fait des deltas de fichiers, mais il les enregistre en tant que delta de l'arborescence de fichiers entière.

Pour voir les différences entre les versions, effectuez l'une des opérations suivantes:

  1. git diff - affiche les différences entre la dernière version archivée et les fichiers qui ont été modifiés, mais qui ne les ont pas git addexécutés.
  2. git diff --cached - montre les différences entre la version précédente et ce que tous les fichiers qui ont été git addexécutés, mais qui n'ont pas été validés
  3. git diff commitid - affiche les différences entre le répertoire de travail actuel et un commit précédent comme spécifié avec le commitid
  4. git diff commita..commitb - montre les différences entre deux commits, a et b. Les validations peuvent également être des noms symboliques comme des branches ou des balises.

Cette réponse n'est pas vraiment correcte. Toutes ces commandes peuvent être appliquées à un ensemble arbitraire de fichiers ainsi qu'à l'ensemble de l'arborescence - il suffit d'ajouter les noms de fichiers à la fin ...
naught101
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.