Que signifie tree-ish dans Git?

122

Je ne sais pas trop comment l'utiliser git archive.

J'ai un référentiel git avec le dossier Foo , Bar et Baz au niveau supérieur. J'ai besoin d'exporter le dossier Foo d'une manière SVN-ish pour un déploiement de test rapide.

J'ai appris que je pouvais utiliser git-archiveune sorte d'exportation SVN-ish .

Mais voici la chose, ce qui suit fonctionne bien:

git archive master | tar -x -C ~/destination

il en résulte des dossiers Foo , Bar , Baz dans le dossier de destination .

Cependant, ce qui suit sera une erreur avec fatal not a valid object name:

git archive master/foo | tar -x -C ~/destination

La documentation

En regardant le synopsis du git archiveprogramme, je vois qu'il peut prendre un <tree-ish> [path]comme paramètre (synopsis résumé aux parties pertinentes):

git archive <tree-ish> [path...]

Si master/foo non tree-ish, qu'est-ce que c'est?

Dkinzer
la source
2
master:fooest un arbre, mais il vaut mieux l'utiliser master foocomme i <tree-ish> <path>.
Jakub Narębski
1
J'avais interprété <tree-ish> comme un adjectif de [chemin]. C'est là que je me suis trompé. Et tous les exemples que j'ai vus n'utilisaient que la partie <tree-ish> de la commande, donc j'avais supposé à tort qu'ils utilisaient un chemin '<tree-ish>. Oh semantics :)
dkinzer
3
J'ai un problème avec cette question parce que le titre demande ce qu'est l'arbre-ish dans git mais ensuite il commence et semble être principalement à propos d'une commande. De plus, la réponse acceptée ne semble pas aborder la signification exacte du terme tree-ish. Soit le titre de la question doit changer, soit la question doit changer. Je suggère que le titre soit mieux adapté à l'objet de la question et à la réponse acceptée. Ou peut-être changer la réponse acceptée en ce que le titre de la question est vraiment. Ou la réponse doit aborder le titre de la question.
Charlie Parker
@CharlieParker apparemment, les pages de manuel de git archivecommande ne font plus référence à tree-ish, mais quand j'ai posé cette question, ils l'ont fait. Et concernant la réponse acceptée; à l'époque, personne d'autre ne s'est donné la peine de répondre à la question. C'est plus de deux ans plus tard qu'une autre réponse avait même été postée.
dkinzer

Réponses:

167

La réponse courte (TL; DR)

"Tree-ish" est un terme qui fait référence à tout identifiant (comme spécifié dans la documentation des révisions de Git ) qui mène finalement à une (sous) arborescence de répertoires (Git se réfère aux répertoires comme des "arbres" et des "objets d'arborescence").

Dans le cas de l'affiche d'origine, foo c'est un répertoire qu'il souhaite spécifier. La manière correcte de spécifier un (sous) répertoire dans Git est d'utiliser cette syntaxe "tree-ish" (élément n ° 15 de la documentation des révisions Git ):

<rev>:<path>, Par exemple HEAD:README, :README,master:./README

Un suffixe :suivi d'un chemin nomme l'objet blob ou l'arborescence au chemin donné dans l'objet arborescent nommé par la partie avant les deux-points.

Donc, en d'autres termes, master:foola syntaxe est correcte, non master/foo.

Autre "Tree-ish" (Plus Commit-ish)

Voici une liste complète des identifiants commit-ish et tree-ish (de la documentation des révisions Git , merci à LopSae pour l'avoir signalé ):

----------------------------------------------------------------------
|    Commit-ish/Tree-ish    |                Examples
----------------------------------------------------------------------
|  1. <sha1>                | dae86e1950b1277e545cee180551750029cfe735
|  2. <describeOutput>      | v1.7.4.2-679-g3bee7fb
|  3. <refname>             | master, heads/master, refs/heads/master
|  4. <refname>@{<date>}    | master@{yesterday}, HEAD@{5 minutes ago}
|  5. <refname>@{<n>}       | master@{1}
|  6. @{<n>}                | @{1}
|  7. @{-<n>}               | @{-1}
|  8. <refname>@{upstream}  | master@{upstream}, @{u}
|  9. <rev>^                | HEAD^, v1.5.1^0
| 10. <rev>~<n>             | master~3
| 11. <rev>^{<type>}        | v0.99.8^{commit}
| 12. <rev>^{}              | v0.99.8^{}
| 13. <rev>^{/<text>}       | HEAD^{/fix nasty bug}
| 14. :/<text>              | :/fix nasty bug
----------------------------------------------------------------------
|       Tree-ish only       |                Examples
----------------------------------------------------------------------
| 15. <rev>:<path>          | HEAD:README, :README, master:./README
----------------------------------------------------------------------
|         Tree-ish?         |                Examples
----------------------------------------------------------------------
| 16. :<n>:<path>           | :0:README, :README
----------------------------------------------------------------------

Les identifiants # 1-14 sont tous "commit-ish", car ils mènent tous à des commits, mais comme les commits pointent également vers des arborescences de répertoires, ils mènent tous finalement à des objets d'arborescence de (sous) répertoires, et peuvent donc également être utilisés comme "arborescence" -ish ".

# 15 peut également être utilisé comme arborescence quand il fait référence à un (sous) répertoire, mais il peut également être utilisé pour identifier des fichiers spécifiques. Quand il fait référence à des fichiers, je ne suis pas sûr s'il est toujours considéré comme "tree-ish", ou s'il agit plus comme "blob-ish" (Git se réfère aux fichiers comme "blobs").

La longue réponse

À ses niveaux les plus bas, Git assure le suivi du code source à l'aide de quatre objets fondamentaux:

  1. Balises annotées, qui pointent vers des commits.
  2. Commits, qui pointent vers l'arborescence de répertoires racine de votre projet.
  3. Les arbres, qui sont des répertoires et des sous-répertoires.
  4. Blobs, qui sont des fichiers.

Chacun de ces objets a son propre ID de hachage sha1, puisque Linus Torvalds a conçu Git comme un système de fichiers adressable par le contenu , c'est-à-dire que les fichiers peuvent être récupérés en fonction de leur contenu (les ID sha1 sont générés à partir du contenu du fichier). Le livre Pro Git donne cet exemple de diagramme :

Figure 9-3 du livre Pro Git

De nombreuses commandes Git peuvent accepter des identificateurs spéciaux pour les commits et les arborescences de (sous) répertoires:

  • "Commit-ish" sont des identificateurs qui mènent finalement à un objet de commit. Par exemple,

    tag -> commit

  • "Tree-ish" sont des identifiants qui mènent finalement à des objets d'arborescence (ie répertoire).

    tag -> commit -> project-root-directory

Étant donné que les objets de validation pointent toujours vers un objet d'arborescence de répertoires (le répertoire racine de votre projet), tout identificateur qui est "commit-ish" est, par définition, également "tree-ish". En d'autres termes, tout identifiant menant à un objet de validation peut également être utilisé pour conduire à un objet d'arborescence de (sous) répertoires .

Mais comme les objets d'arborescence de répertoires ne pointent jamais vers des commits dans le système de gestion des versions de Git, tous les identificateurs qui pointent vers une (sous) arborescence de répertoires ne peuvent pas également être utilisés pour pointer vers un commit. En d'autres termes, l'ensemble des identifiants «commit-ish» est un sous-ensemble strict de l'ensemble des identifiants «tree-ish».

Comme expliqué dans la documentation ( merci à Trebor de m'avoir aidé à le trouver ):

<tree>

Indique un nom d'objet d'arborescence.

<commit>

Indique un nom d'objet de validation.

<tree-ish>

Indique un nom d'objet d'arborescence, de validation ou de balise. Une commande qui prend un <tree-ish> argument veut finalement opérer sur un <tree>objet mais déréférence automatiquement <commit>et les <tag>objets qui pointent vers un <tree>.

<commit-ish>

Indique un nom d'objet de validation ou de balise. Une commande qui prend un <commit-ish> argument veut finalement opérer sur un <commit>objet mais déréférence automatiquement les <tag>objets qui pointent vers un <commit>.

L'ensemble des identificateurs d'arborescence qui ne peuvent pas être utilisés comme commit-ish sont

  1. <rev>:<path>, qui mène directement aux arborescences de répertoires, pas aux objets de validation. Par exemple HEAD:subdirectory,.

  2. Identifiants Sha1 des objets de l' arborescence de répertoires .

Communauté
la source
Qu'en est-il de l'entrée 16 sur votre table? Cela signifie-t-il que vous ne savez pas si c'est un arbre ou non? Le 0 fait référence à l'état de fusion, et ce concept s'applique uniquement aux objets blob, car l'index ne contient même pas de répertoires. Voir: stackoverflow.com/a/25806452/895245 . Donc, la question se résume alors à: tous les blob-ishes sont-ils aussi des tree-ishes? Pour autant que je peux dire oui: toutes les pages de manuel qui utilisent <tree-ish>accepter à la fois, et man gitrevisionsdéfinit: trees ("directories of files").
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Notez que git-archivecela dit qu'il faut un <tree-ish>mais qu'il interdit un <sha1>. Donc je suppose qu'il faudrait plutôt demander un fichier <tree-ish-ish>. stackoverflow.com/a/12073669/680464
juanitogan
Cependant, je me demande ce qui se passe lorsque j'utilise <rev>: (sans aucun chemin?. Cela fonctionne comme essayé - mais je ne trouve pas de section pertinente dans la documentation.
Martin Vejmelka
49

Un tree-ish est une façon de nommer un arbre spécifique qui peut être l'un des suivants:

  • Références comme:
    • TÊTE
    • Mots clés
    • Noms des succursales
    • Noms de succursales avec télécommandes, comme origin/somebranch
  • Hacher
  • Hachages courts

En plus de cela, tout de ce qui précède peut être joint en annexe avec ^, ~. Les références peuvent également utiliser la @{}notation pour certaines fonctionnalités supplémentaires:

  • HEAD^ou HEAD^1sera résolu au premier parent de HEAD.
  • HEAD^2 se résoudra au deuxième parent
  • HEAD^3se résoudra au troisième parent et ainsi de suite, qui est plus rare et produit des fusions avec la stratégie de poulpe .
  • HEAD~ou HEAD~1se résoudra au premier parent de la tête
  • HEAD~2se résoudra au premier parent du premier parent de HEAD. Ce serait la même chose queHEAD^^
  • HEAD@{0} se résoudra à la tête actuelle
  • HEAD@{1}se résoudra à la tête précédente. Cela ne peut être utilisé que par des références car il utilise le journal de référence. Dans le cas de HEADchaque commit, fusion, checkout changera la valeur de HEAD et l'ajoutera ainsi au journal. git reflog HEADaffichera le journal de référence où vous pouvez voir tous les mouvements de HEAD et correctement ce à quoi @{1}et ainsi de suite résoudra.

La plupart de ce qui précède peut être combiné tant qu'il est logique dans votre référentiel, par exemple: HEAD@{2}~3, somebranch^2~4, c00e66e~4^2, anotherbranch~^~^~^.

Donc, tout ce qui est décrit ci-dessus, et ses combinaisons, est ce que la documentation entend par arborescence, qui est juste un moyen de dire quel arbre (ou révision) est celui qui devrait être utilisé pour la plupart des commandes git.

Plus d'informations dans Revision Selection dans le livre Git .

LopSae
la source
1
Cette réponse explique les révisions (commit-ishes) en général et manque le cas crucial:, master:path/to/directoryqui est un tree-ish mais pas un commit-ish. Cupcake's rend cela plus clair.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
11

Tu veux probablement

git archive master foo | tar -x -C ~/destination

L'expression master/foon'a pas de sens: masterest un nom de branche et fooest un nom de répertoire, comme je le suppose.

Modifier : (Suppression du lien rompu. Voir les commentaires.)

Sven Marnach
la source
Le mot "arbre" ne se trouve plus sur votre lien "Git Treeishes". FYI
Robert
Treeish fait généralement référence à l'arborescence des révisions et non à une présentation de répertoire.
Jürgen Strobel
6
@ JürgenStrobel: Ce n'est pas vrai. Il ne faisait référence à aucun des deux - au passé, car le terme n'est plus utilisé dans la version actuelle de la documentation. (C'est aussi pourquoi le lien est rompu.) Auparavant, un treeish faisait référence à quelque chose qui pouvait être résolu en un objet tree dans le magasin d'objets de git. Cela incluait toute spécification de commit, puisque chaque commit fait référence à un seul objet d'arborescence. L'objet tree contient des informations sur l'arborescence de répertoires de ce commit - voir la section sur les objets git dans "Pro Git" pour plus de détails.
Sven Marnach
6

Pour obtenir les définitions <tree-ish>et <commit-ish>consulter la page de manuel git (1) . Vous devrez rechercher les termes. En général, cela <tree-ish>signifie une référence à un objet d'arborescence git, mais si vous passez un type d'objet qui fait référence à un arbre (tel qu'un commit ou une branche), git utilisera automatiquement l'arborescence référencée.

Trebor Rude
la source
Et gitrevisions(7).
Xiong Chiamiov
0

Je suis un débutant en contrôle de code source et en git. Voilà ce que je sais. Une arborescence est la structure des fichiers dans un référentiel. C'est similaire à un répertoire dans un système de fichiers. Voir - Quel outil git a généré cette arborescence?

Tree-ish signifie comme un arbre. Il fait référence à une partie ou à un commit d'un arbre. Vous pouvez référencer un commit en utilisant l'un de ces éléments: tout ou partie du hachage SHA-1 d'un commit, pointeur HEAD, référence de branche, référence de balise. Une autre méthode utilise l'une des méthodes mentionnées avec les ancêtres ou les parents d'un commit. Exemple d'ancêtres: entrez la description de l'image ici

pile1
la source
0

De Git Glossary tree-ish est "Un objet d'arbre ou un objet qui peut être déréférencé récursivement à un objet d'arbre." commit, HEAD et tag sont des exemples d'objets arborescents.

user2494386
la source