Cosa significa tree-ish in Git?


122

Sono molto confuso su come usare git archive.

Ho un repository git con la cartella Foo , Bar e Baz al livello superiore. Ho bisogno di esportare la cartella Foo in un modo simile a SVN per una rapida distribuzione di prova.

Ho imparato che potevo usare git-archivein una sorta di esportazione SVN-ish .

Ma ecco il punto, quanto segue funziona bene:

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

risulta nelle cartelle Foo , Bar , Baz nella cartella di destinazione .

Tuttavia, il seguente errore si verificherà con fatal not a valid object name:

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

La documentazione

Guardando la sinossi del git archiveprogramma vedo che può prendere un <tree-ish> [path]come parametro (sinossi riassunta nelle parti pertinenti):

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

Se master/foo non lo è tree-ish, allora cos'è?


2
master:fooè albero-ish, ma è meglio usare master foocome i <tree-ish> <path>.
— Jakub Narębski

1
Avevo interpretato <tree-ish> come un aggettivo di [path]. Ecco dove ho sbagliato. E tutti gli esempi che ho visto usavano solo la parte <tree-ish> del comando, quindi avevo erroneamente supposto che stessero usando un percorso '<tree-ish>. Oh semantica :)
— dkinzer


3
Ho un problema con questa domanda perché il titolo chiede cosa sia tree-ish in git ma poi inizia e sembra riguardare principalmente alcuni comandi. Inoltre, la risposta accettata non sembra affrontare esattamente il significato del termine albero-ish. O il titolo della domanda deve cambiare o la domanda deve cambiare. Suggerisco che il titolo si adatti meglio a ciò di cui si tratta veramente la domanda e quale fosse la risposta accettata. O forse cambiando la risposta accettata a qual è realmente il titolo della domanda. Oppure la risposta dovrebbe riguardare il titolo della domanda.
— Charlie Parker

@CharlieParker apparentemente le pagine man per il git archivecomando non si riferiscono più a tree-ish, ma quando ho posto questa domanda lo hanno fatto. E per quanto riguarda la risposta accettata; al momento nessun altro si è preso la briga di rispondere alla domanda. Più di due anni dopo fu persino pubblicata un'altra risposta.
— dkinzer

Risposte:


167

La risposta breve (TL; DR)

"Tree-ish" è un termine che si riferisce a qualsiasi identificatore (come specificato nella documentazione delle revisioni di Git ) che alla fine porta a un (sotto) albero di directory (Git si riferisce alle directory come "alberi" e "oggetti albero").

Nel caso del poster originale, foo è una directory che vuole specificare. Il modo corretto per specificare una (sotto) directory in Git è usare questa sintassi "ad albero" (elemento # 15 dalla documentazione delle revisioni di Git ):

<rev>:<path>, Ad esempio HEAD:README, :README,master:./README

Un suffisso :seguito da un percorso denomina il blob o l'albero nel percorso specificato nell'oggetto tree-ish denominato dalla parte prima dei due punti.

Quindi, in altre parole, master:fooè la sintassi corretta, no master/foo.

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

Ecco un elenco completo di identificatori di commit e tree-ish (dalla documentazione delle revisioni di Git , grazie a LopSae per averlo segnalato ):

----------------------------------------------------------------------
|    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
----------------------------------------------------------------------

Gli identificatori # 1-14 sono tutti "commit-ish", perché tutti portano a commit, ma poiché i commit puntano anche ad alberi di directory, alla fine portano tutti a oggetti (sotto) albero di directory, e possono quindi essere usati anche come "albero -ish".

# 15 può anche essere usato come tree-ish quando si riferisce a una (sotto) directory, ma può anche essere usato per identificare file specifici. Quando si riferisce ai file, non sono sicuro che sia ancora considerato "tree-ish", o se agisce più come "blob-ish" (Git si riferisce ai file come "blob").

La lunga risposta

Ai livelli più bassi, Git tiene traccia del codice sorgente utilizzando quattro oggetti fondamentali:

  1. Tag annotati, che puntano ai commit.
  2. Commits, che puntano all'albero della directory principale del progetto.
  3. Alberi, che sono directory e sottodirectory.
  4. Blob, che sono file.

Ciascuno di questi oggetti ha il proprio hash ID sha1, poiché Linus Torvalds ha progettato Git come un filesystem indirizzabile al contenuto , cioè i file possono essere recuperati in base al loro contenuto (gli ID sha1 sono generati dal contenuto del file). Il libro Pro Git fornisce questo diagramma di esempio :

Figura 9-3 dal libro Pro Git

Molti comandi Git possono accettare identificatori speciali per commit e (sotto) alberi di directory:

  • "Commit-ish" sono identificatori che alla fine portano a un oggetto di commit. Per esempio,

    tag -> commit

  • "Tree-ish" sono identificatori che alla fine portano a oggetti ad albero (cioè directory).

    tag -> commit -> project-root-directory

Poiché gli oggetti commit puntano sempre a un oggetto albero di directory (la directory radice del progetto), qualsiasi identificatore "commit-ish" è, per definizione, anche "tree-ish". In altre parole, qualsiasi identificatore che porta a un oggetto commit può anche essere utilizzato per portare a un (sotto) oggetto albero di directory .

Ma poiché gli oggetti dell'albero di directory non puntano mai ai commit nel sistema di controllo delle versioni di Git, non tutti gli identificatori che puntano a un (sotto) albero di directory possono anche essere usati per puntare a un commit. In altre parole, l'insieme di identificatori "commit-ish" è un sottoinsieme rigoroso dell'insieme di identificatori "tree-ish".

Come spiegato nella documentazione ( grazie a Trebor per avermi aiutato a trovarlo ):

<tree>

Indica il nome di un oggetto albero.

<commit>

Indica il nome di un oggetto di commit.

<tree-ish>

Indica un nome di oggetto albero, commit o tag. Un comando che accetta un <tree-ish> argomento alla fine vuole operare su un <tree>oggetto ma dereferisce automaticamente <commit>e gli <tag>oggetti che puntano a <tree>.

<commit-ish>

Indica il nome di un oggetto di commit o tag. Un comando che accetta un <commit-ish> argomento alla fine vuole operare su un <commit>oggetto ma dereferenzia automaticamente gli <tag>oggetti che puntano a <commit>.

L'insieme di identificatori ad albero che non possono essere usati come commit-ish sono

  1. <rev>:<path>, che porta direttamente agli alberi di directory, non agli oggetti di commit. Ad esempio HEAD:subdirectory,.

  2. Identificatori Sha1 degli oggetti dell'albero di directory .


E la voce 16 sul tuo tavolo? Significa che non sei sicuro che sia un albero o no? Lo 0 si riferisce allo stato di unione e questo concetto si applica solo ai BLOB, poiché l'indice non contiene nemmeno directory. Vedi: stackoverflow.com/a/25806452/895245 . Quindi la domanda si riduce a: tutti i blob-ish sono anche tree-ishes? Per quanto posso dire di sì: tutte le pagine che utilizzano <tree-ish>accettare sia, e man gitrevisionsdefinisce: trees ("directories of files").
— Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Nota che git-archivedice che ci vuole un <tree-ish>ma non consente a <sha1>. Quindi immagino che dovrebbe invece chiedere un file <tree-ish-ish>. stackoverflow.com/a/12073669/680464
— juanitogan

Tuttavia mi chiedo cosa succede quando utilizzo <rev>: (senza alcun percorso ?. Funziona come provato - ma non riesco a trovare la sezione pertinente nella documentazione.
— Martin Vejmelka

49

Un albero è un modo di nominare un albero specifico che può essere uno dei seguenti:

  • Riferimenti come:
    • TESTA
    • tag
    • Nomi delle filiali
    • Nomi di filiali con telecomandi, come origin/somebranch
  • hash
  • Hash brevi

In cima a quello, una di queste può essere aggiunto con ^, ~. I riferimenti possono anche utilizzare la @{}notazione per alcune funzionalità aggiuntive:

  • HEAD^o HEAD^1verrà risolto al primo genitore di HEAD.
  • HEAD^2 risolverà al secondo genitore
  • HEAD^3si risolverà al terzo genitore e così via, che è più raro e prodotto di fusioni con la strategia del polpo .
  • HEAD~o HEAD~1risolverà al primo genitore di testa
  • HEAD~2risolverà al primo genitore del primo genitore di HEAD. Questo sarebbe lo stesso diHEAD^^
  • HEAD@{0} si risolverà nell'HEAD corrente
  • HEAD@{1}risolverà alla testa precedente. Può essere utilizzato solo dai riferimenti poiché utilizza il registro dei riferimenti. Nel caso di HEADogni commit, merge, checkout cambierà il valore di HEAD e quindi lo aggiungerà al log. git reflog HEADmostrerà il registro di riferimento dove puoi vedere tutti i movimenti di TESTA e correttamente cosa @{1}si risolverà e così via.

La maggior parte di quanto sopra può essere ulteriormente combinati finché ha senso nel vostro repository, per esempio: HEAD@{2}~3, somebranch^2~4, c00e66e~4^2, anotherbranch~^~^~^.

Quindi uno qualsiasi degli elementi descritti sopra, e le sue combinazioni, è ciò che si intende nella documentazione come un albero, che è solo un modo per dire quale albero (o revisione) è quello che dovrebbe essere usato per la maggior parte dei comandi git.

Maggiori informazioni in Revision Selection nel libro Git .


1
Questa risposta spiega le revisioni (commit-ishes) in generale e manca il caso cruciale:, master:path/to/directoryche è un albero ma non un commit. Cupcake's lo rende più chiaro.
— Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

11

Probabilmente lo vuoi

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

L'espressione master/foonon ha senso: masterè un nome di ramo ed fooè un nome di directory, come presumo.

Modifica : (link interrotto rimosso. Vedi commenti.)


La parola "albero" non si trova più sul tuo link "Git Treeishes". Cordiali saluti
— Robert

Treeish si riferisce generalmente all'albero delle revisioni, non al layout di una directory.
— Jürgen Strobel

6
@ JürgenStrobel: non è vero. Non si riferiva a nessuno dei due - al passato, perché il termine non è più utilizzato nella versione corrente della documentazione. (Questo è anche il motivo per cui il collegamento è interrotto.) In precedenza, un albero si riferiva a qualcosa che poteva essere risolto in un oggetto albero nell'archivio oggetti di git. Ciò includeva qualsiasi specifica di commit, poiché ogni commit si riferisce a un singolo oggetto albero. L'oggetto albero contiene informazioni sull'albero delle directory di questo commit - vedere la sezione sugli oggetti git in "Pro Git" per i dettagli.
— Sven Marnach

6

Per le definizioni <tree-ish>e <commit-ish>vedere la pagina man git (1) . Dovrai cercare i termini. In generale si <tree-ish>intende un riferimento a un oggetto albero git, ma se si passa un tipo di oggetto che fa riferimento a un albero (come un commit o un ramo), git utilizzerà automaticamente l'albero di riferimento.


E gitrevisions(7).
— Xiong Chiamiov

0

Sono un principiante del controllo del codice sorgente e di git. Questo è quello che so. Un albero è la struttura dei file in un repository. È simile a una directory in un file system Vedi - Quale strumento git ha generato questa visualizzazione ad albero?

Tree-ish significa come un albero. Fa riferimento a una parte o commit di un albero. Puoi fare riferimento a un commit usando uno qualsiasi di questi: completo o parte dell'hash SHA-1 di un commit, puntatore HEAD, riferimento al ramo, riferimento al tag. Un altro metodo utilizza uno dei metodi menzionati insieme agli antenati o ai genitori di un commit. Esempio di antenati: inserisci qui la descrizione dell'immagine


0

Dal glossario di Git tree-ish è "Un oggetto albero o un oggetto che può essere dereferenziato ricorsivamente a un oggetto albero". commit, HEAD e tag sono esempi di oggetti tree-ish.

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.