O que são commit-ish e tree-ish no Git?

117

A questão

Quais são os exemplos específicos de commit-ish e tree-ish no Git?

A questão Stack Overflow "O que tree-ish significa no git?" lida especificamente com arborismo, mas quero entender mais sobre ambos .

fundo

Usos na documentação

A documentação do Git faz várias referências a "commit-ish" e "tree-ish". Por exemplo, se você estiver examinando o código-fonte Git :

$ git grep --files-with-matches --extended-regexp "commit(-)*ish"
config.txt
git-describe.txt
git-fast-import.txt
git-name-rev.txt
git-push.txt
git-rebase.txt
git-rev-parse.txt
git.txt
gitcli.txt
glossary-content.txt
howto/revert-branch-rebase.txt
revisions.txt

e

$ git grep --files-with-matches --extended-regexp "tree(-)*ish" | \
$ grep --invert-match RelNotes
diff-format.txt
diff-generate-patch.txt
git-archive.txt
git-cat-file.txt
git-checkout.txt
git-diff-index.txt
git-diff-tree.txt
git-ls-files.txt
git-ls-tree.txt
git-merge-tree.txt
git-read-tree.txt
git-reset.txt
git-svn.txt
git.txt
gitcli.txt
gittutorial-2.txt
glossary-content.txt
revisions.txt

Definições

A documentação do Git define o que são "commit-ish" e "tree-ish" :

<tree>

Indica um nome de objeto de árvore.

<commit>

Indica um nome de objeto de confirmação.

<tree-ish>

Indica um nome de objeto de árvore, confirmação ou tag. Um comando que leva um <tree-ish> argumento em última análise, quer operar em um <tree>objeto, mas automaticamente dereferences <commit>e <tag>objetos que ponto em um <tree>.

<commit-ish>

Indica um nome de objeto de confirmação ou tag. Um comando que recebe um <commit-ish> argumento, em última análise, deseja operar em um <commit>objeto, mas desreferencia automaticamente os <tag>objetos que apontam para a <commit>.

A documentação não é suficientemente clara

Embora a documentação acima defina o que são "commit-ish" e "tree-ish", ainda acho que é muito vago e confuso.

Quais são os exemplos específicos de "commit-ish" e "tree-ish", e como eles são diferentes um do outro?

Comunidade
fonte

Respostas:

156

A resposta curta (TL; DR)

Aqui está uma lista completa de identificadores commit-ish e tree-ish (da documentação de revisões do Git ):

----------------------------------------------------------------------
|    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.txt, master:sub-directory/
----------------------------------------------------------------------
|         Tree-ish?         |                Examples
----------------------------------------------------------------------
| 16. :<n>:<path>           | :0:README, :README
----------------------------------------------------------------------

Os identificadores # 1-14 são todos "commit-ish", porque todos eles levam a commits, mas porque os commits também apontam para árvores de diretórios, todos eles levam a objetos da árvore de (sub) diretórios e, portanto, também podem ser usados ​​como "árvore -ish ".

# 15 também pode ser usado como uma árvore quando se refere a um (sub) diretório, mas também pode ser usado para identificar arquivos específicos. Quando se refere a arquivos, não tenho certeza se ainda é considerado "arvore" ou se age mais como "blob-ish" (Git se refere a arquivos como "blobs").

A resposta longa

Commits e árvores de diretório no Git

Em seus níveis mais baixos, o Git acompanha o código-fonte usando quatro objetos fundamentais:

  1. Tags anotadas, que apontam para commits.
  2. Commits, que apontam para a árvore do diretório raiz do seu projeto.
  3. Árvores, que são diretórios e subdiretórios.
  4. Blobs, que são arquivos.

Cada um desses objetos tem seu próprio sha1 hash ID, já que Linus Torvalds projetou o Git como um sistema de arquivos endereçável por conteúdo , ou seja, os arquivos podem ser recuperados com base em seu conteúdo (sha1 IDs são gerados a partir do conteúdo do arquivo). O livro Pro Git fornece este diagrama de exemplo :

Figura 9-3 do livro Pro Git

Commit-ish vs Tree-ish

Muitos comandos Git podem aceitar identificadores especiais para commits e árvores de (sub) diretórios:

  • "Commit-ish" são identificadores que, em última análise, levam a um objeto de confirmação. Por exemplo,

    tag -> commit

  • "Tree-ish" são identificadores que levam a objetos de árvore (isto é, diretório).

    tag -> commit -> project-root-directory

Como os objetos de commit sempre apontam para um objeto de árvore de diretório (o diretório raiz de seu projeto), qualquer identificador que seja "commit-ish" é, por definição, também "tree-ish". Em outras palavras, qualquer identificador que leva a um objeto de confirmação também pode ser usado para conduzir a um objeto de árvore de (sub) diretório .

Mas, uma vez que os objetos da árvore de diretório nunca apontam para commits no sistema de versionamento do Git, nem todo identificador que aponta para uma árvore de (sub) diretório também pode ser usado para apontar para um commit. Em outras palavras, o conjunto de identificadores "commit-ish" é um subconjunto estrito do conjunto de identificadores "tree-ish".

O conjunto de identificadores ish de árvore que não podem ser usados ​​como commit-ish são

  1. <rev>:<path>, que leva diretamente a árvores de diretório, não a objetos de commit. Por exemplo HEAD:subdirectory,.

  2. Identificadores Sha1 de objetos de árvore de diretório .


fonte
3
Não se esqueça stash@{0}. Eu gostaria de saber onde isso se encaixa em tudo isso. Existem outras coisas como o stash ( my-thing@{0})? O estoque é apenas um <refname>?
Nate
Não ficou claro explicitamente que um identificador tipo árvore parece ser um identificador mais específico do que um identificador commit-ish. Talvez eu seja estranho, mas essa é a única maneira sensata de explicar isso. IMO
Steven Lu
29

Nota para falantes não nativos de inglês [sic!]: "-Ish" é um sufixo que pode ser aplicado a um adjetivo para indicar "tendo qualidades como" ou "ligeiramente" - consulte http://chambers.co.uk / search /? query = ish & title = 21st

Daí "árvore-ish" - como uma "árvore" .... "commit-ish" - como um "commit"

por exemplo, "Marte aparece como uma estrela avermelhada" ("d" é duplicado!); "a comida no prato não estava quente, mas morna"

Acredito que isso ajuda a explicar "o que é ..." melhor, na medida em que explica o uso da linguagem.

MikeW
fonte
Sempre interpretei "tree-ish" e "commit-ish" como sendo análogos a dizer "sueco" ou "inglês". O uso que você descreve faz menos sentido para mim porque essa forma de "ish" cria um adjetivo. Mas o rev não é "como" uma árvore ou commit, é uma árvore ou commit. Por outro lado, se você pensar em "ish" como um sufixo de idioma, eles farão mais sentido como substantivos na linha de comando, onde "ish em árvore" é a linguagem que forma o substantivo. Não sei qual interpretação foi a intenção dos autores, mas é assim que sempre vi.
jmt
Eu entendo seu ponto, mas eu estava apenas dando a impressão que tenho, como falante nativo de inglês!
MikeW