¿Qué significa tree-ish en Git?

122

Estoy muy confundido acerca de cómo usarlo git archive.

Tengo un repositorio de git con la carpeta Foo , Bar y Baz en el nivel superior. Necesito exportar la carpeta Foo de una forma similar a SVN para una implementación de prueba rápida.

Aprendí que podía usarlo git-archiveen una especie de exportación de SVN .

Pero aquí está la cosa, lo siguiente funciona bien:

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

da como resultado las carpetas Foo , Bar , Baz en la carpeta de destino .

Sin embargo, lo siguiente generará un error con fatal not a valid object name:

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

La documentación

Mirando como la sinopsis del git archiveprograma, veo que puede tomar a <tree-ish> [path]como parámetro (sinopsis resumida en partes relevantes):

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

Si master/foo no es así tree-ish, ¿qué es?

dkinzer
fuente
2
master:fooes un árbol, pero es mejor usarlo master foocomo i <tree-ish> <path>.
Jakub Narębski
1
Había interpretado <tree-ish> como un adjetivo de [ruta]. Ahí es donde me equivoqué. Y todos los ejemplos que vi solo usaban la parte <tree-ish> del comando, por lo que asumí erróneamente que estaban usando una ruta '<tree-ish>. Oh semántica :)
dkinzer
3
Tengo un problema con esta pregunta porque el título pregunta sobre qué tipo de árbol está en git, pero luego comienza y parece ser principalmente sobre algún comando. Además, la respuesta aceptada no parece abordar lo que significa exactamente el término árbol-ish. O el título de la pregunta debe cambiar o la pregunta debe cambiar. Sugiero que el título se adapte mejor a lo que realmente trata la pregunta y cuál fue la respuesta aceptada. O tal vez cambiar la respuesta aceptada a cuál es realmente el título de la pregunta. O la respuesta debe abordar el título de la pregunta.
Charlie Parker
@CharlieParker aparentemente las páginas de manual para el git archivecomando ya no se refieren al árbol, pero cuando hice esta pregunta lo hicieron. Y en cuanto a la respuesta aceptada; en ese momento nadie más se molestó en responder la pregunta. Fue más de dos años después que incluso se publicó otra respuesta.
dkinzer

Respuestas:

167

La respuesta corta (TL; DR)

"Tree-ish" es un término que se refiere a cualquier identificador (como se especifica en la documentación de revisiones de Git ) que finalmente conduce a un árbol de (sub) directorio (Git se refiere a los directorios como "árboles" y "objetos de árbol").

En el caso del cartel original, foo es un directorio que quiere especificar. La forma correcta de especificar un (sub) directorio en Git es usar esta sintaxis "en árbol" (elemento # 15 de la documentación de revisiones de Git ):

<rev>:<path>, Por ejemplo HEAD:README, :README,master:./README

Un sufijo :seguido de una ruta nombra el blob o el árbol en la ruta dada en el objeto en forma de árbol nombrado por la parte antes de los dos puntos.

Entonces, en otras palabras, master:fooes la sintaxis correcta, no master/foo.

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

Aquí hay una lista completa de identificadores de tipo commit-ish y tree-ish (de la documentación de revisiones de Git , gracias a LopSae por señalarlo ):

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

Los identificadores # 1-14 son todos "commit-ish", porque todos conducen a confirmaciones, pero debido a que las confirmaciones también apuntan a árboles de directorio, todos finalmente conducen a objetos de árbol de (sub) directorio y, por lo tanto, también se pueden usar como "árbol -ish ".

# 15 también se puede usar como árbol cuando se refiere a un (sub) directorio, pero también se puede usar para identificar archivos específicos. Cuando se refiere a archivos, no estoy seguro si todavía se considera "tipo árbol", o si actúa más como "tipo blob" (Git se refiere a archivos como "blobs").

La respuesta larga

En sus niveles más bajos, Git realiza un seguimiento del código fuente utilizando cuatro objetos fundamentales:

  1. Etiquetas anotadas, que apuntan a confirmaciones.
  2. Confirma, que apunta al árbol del directorio raíz de su proyecto.
  3. Árboles, que son directorios y subdirectorios.
  4. Blobs, que son archivos.

Cada uno de estos objetos tiene su propio ID de hash sha1, ya que Linus Torvalds diseñó Git como un sistema de archivos direccionable por contenido , es decir, los archivos se pueden recuperar en función de su contenido (los ID de sha1 se generan a partir del contenido del archivo). El libro Pro Git ofrece este diagrama de ejemplo :

Figura 9-3 del libro Pro Git

Muchos comandos de Git pueden aceptar identificadores especiales para confirmaciones y árboles de (sub) directorio:

  • "Commit-ish" son identificadores que finalmente conducen a un objeto de confirmación. Por ejemplo,

    tag -> commit

  • "Tree-ish" son identificadores que finalmente conducen a objetos de árbol (es decir, directorio).

    tag -> commit -> project-root-directory

Debido a que los objetos de confirmación siempre apuntan a un objeto de árbol de directorio (el directorio raíz de su proyecto), cualquier identificador que sea "commit-ish" es, por definición, también "tree-ish". En otras palabras, cualquier identificador que lleve a un objeto de confirmación también se puede utilizar para llevar a un objeto de árbol de (sub) directorio .

Pero dado que los objetos del árbol de directorios nunca apuntan a confirmaciones en el sistema de control de versiones de Git, no todos los identificadores que apuntan a un (sub) árbol de directorios también pueden usarse para señalar una confirmación. En otras palabras, el conjunto de identificadores de "compromiso" es un subconjunto estricto del conjunto de identificadores de "árbol".

Como se explica en la documentación ( gracias a Trebor por ayudarme a encontrarlo ):

<tree>

Indica un nombre de objeto de árbol.

<commit>

Indica un nombre de objeto de confirmación.

<tree-ish>

Indica un árbol, un compromiso o un nombre de objeto de etiqueta. Un comando que toma un <tree-ish> argumento, en última instancia, quiere operar en un <tree>objeto, pero elimina automáticamente las referencias <commit>y los <tag>objetos que apuntan a un <tree>.

<commit-ish>

Indica un nombre de objeto de confirmación o etiqueta. Un comando que toma un <commit-ish> argumento en última instancia, quiere operar en un <commit>objeto, pero automáticamente elimina las referencias a los <tag>objetos que apuntan a un <commit>.

El conjunto de identificadores de tipo árbol que no se pueden utilizar como compromiso son

  1. <rev>:<path>, que conduce directamente a árboles de directorios, no a enviar objetos. Por ejemplo HEAD:subdirectory,.

  2. Identificadores Sha1 de objetos de árbol de directorio .

Comunidad
fuente
¿Qué pasa con la entrada 16 en su mesa? ¿Significa que no estás seguro de si es un árbol o no? El 0 se refiere al estado de fusión, y este concepto se aplica solo a los blobs, ya que el índice ni siquiera contiene directorios. Consulte: stackoverflow.com/a/25806452/895245 . Entonces, la pregunta se reduce a: ¿son todas las manchas también las capas de los árboles? Por lo que yo puedo decir que sí: todas las páginas del manual que utilizan <tree-ish>aceptar ambos, y man gitrevisionsdefine: trees ("directories of files").
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Tenga en cuenta que git-archivedice que toma un <tree-ish>pero no permite un <sha1>. Así que supongo que debería pedir un <tree-ish-ish>. stackoverflow.com/a/12073669/680464
juanitogan
Sin embargo, me pregunto qué sucede cuando uso <rev>: (¿sin ninguna ruta? Funciona como se intentó, pero no puedo encontrar la sección relevante en la documentación.
Martin Vejmelka
49

Un árbol es una forma de nombrar un árbol específico que puede ser uno de los siguientes:

  • Referencias como:
    • CABEZA
    • Etiquetas
    • Nombres de sucursales
    • Nombres de sucursales con controles remotos, como origin/somebranch
  • Picadillo
  • Hashes cortos

Además de eso, cualquiera de los anteriores puede ser adjunta con ^, ~. Las referencias también pueden usar la @{}notación para algunas características adicionales:

  • HEAD^o HEAD^1se resolverá con el primer padre de HEAD.
  • HEAD^2 se resolverá con el segundo padre
  • HEAD^3se resolverá con el tercer padre y así sucesivamente, lo que es más raro y producto de fusiones con la estrategia del pulpo .
  • HEAD~o HEAD~1se resolverá con el primer padre del jefe
  • HEAD~2resolverá al primer padre del primer padre de HEAD. Esto sería lo mismo queHEAD^^
  • HEAD@{0} se resolverá en el HEAD actual
  • HEAD@{1}Resolverá al encabezado anterior. Esto solo puede ser utilizado por referencias ya que hace uso del registro de referencia. En el caso de HEADcada commit, merge, checkout cambiará el valor de HEAD y así lo agregará al registro. git reflog HEADmostrará el registro de referencia donde puede ver todos los movimientos de HEAD y correctamente qué @{1}se resolverá.

La mayoría de los anteriores se pueden combinar más, siempre y cuando tenga sentido en su repositorio, por ejemplo: HEAD@{2}~3, somebranch^2~4, c00e66e~4^2, anotherbranch~^~^~^.

Entonces, cualquiera de los descritos anteriormente, y sus combinaciones, es lo que se entiende en la documentación como un árbol, que es solo una forma de decir qué árbol (o revisión) es el que debe usarse para la mayoría de los comandos de git.

Más información en Selección de revisión en el libro de Git .

LopSae
fuente
1
Esta respuesta explica las revisiones (confirmaciones) en general y omite el caso crucial:, master:path/to/directoryque es un árbol pero no una confirmación. Cupcake's lo hace más claro.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
11

Probablemente quieras

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

La expresión master/foono tiene sentido: masteres un nombre de rama y fooes un nombre de directorio, como supongo.

Editar : (Se eliminó el enlace roto. Ver comentarios).

Sven Marnach
fuente
La palabra "árbol" ya no se encuentra en su enlace "Git Treeishes". FYI
Robert
Treeish generalmente se refiere al árbol de revisión, no al diseño de un directorio.
Jürgen Strobel
6
@ JürgenStrobel: Eso no es cierto. No se refería a ninguno de los dos, en tiempo pasado, porque el término ya no se usa en la versión actual de la documentación. (Esa es también la razón por la que el enlace está roto). Anteriormente, un treeish se refería a algo que podría resolverse en un objeto de árbol en el almacén de objetos de git. Esto incluía cualquier especificación de confirmación, ya que cada confirmación se refiere a un único objeto de árbol. El objeto de árbol contiene información sobre el árbol de directorios de esta confirmación; consulte la sección sobre objetos git en "Pro Git" para obtener más detalles.
Sven Marnach
6

Para obtener definiciones de <tree-ish>y <commit-ish>consulte la página de manual de git (1) . Tendrá que buscar los términos. En general, <tree-ish>significa una referencia a un objeto de árbol de git, pero si pasa un tipo de objeto que hace referencia a un árbol (como una confirmación o una rama), git usará automáticamente el árbol de referencia.

Trebor Rude
fuente
Y gitrevisions(7).
Xiong Chiamiov
0

Soy un novato en el control de fuentes y git. Eso es lo que sé. Un árbol es la estructura de archivos en un repositorio. Es similar a un directorio en un sistema de archivos. Consulte - ¿Qué herramienta git generó esta vista de árbol?

Tree-ish significa como un árbol. Hace referencia a una parte o compromiso de un árbol. Puede hacer referencia a una confirmación utilizando cualquiera de estos: total o parte del hash SHA-1 de una confirmación, puntero HEAD, referencia de rama, referencia de etiqueta. Otro método usa cualquiera de los métodos mencionados junto con los antepasados ​​o padres de un compromiso. Ejemplo de antepasados: ingrese la descripción de la imagen aquí

stack1
fuente
0

De Git Glossary tree-ish es "Un objeto de árbol o un objeto que puede desreferenciarse recursivamente a un objeto de árbol". commit, HEAD y tag son ejemplos de objetos en forma de árbol.

usuario2494386
fuente