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.