Guía9 min

git archive para coding agents: snapshot del tree, no otro clone

Resumen

git archive empaqueta un tree-ish (HEAD, tag, SHA) en tar/zip. -o + --prefix=dir/. Cero stdout al LLM. Cero --remote autónomo. Cero prefix sin slash. No es clone ni bundle. Git 2.50.1.

GitHub
Un tree de commit entra a un tar.gz con prefix; untracked y el working tree sucio quedan fuera

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

git archive crea un archivo (tar/zip) con el tree de un commit, tag o tree. El man (git-archive(1); git-scm.com/docs/git-archive HTTP 200, last-modified 2026-08-31; pie del man local Git 2.50.1.428.g0e8243, 2025-07-22; binario Git 2.50.1 / Apple Git-155): Create an archive of files from a named tree. SYNOPSIS: git archive [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>] [-o <file> | --output=<file>] [--worktree-attributes] [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish> [<path>...].

No es clone. Clone copia el objeto store y deja un repo. Archive no deja .git. Tampoco es un worktree: worktree es otro checkout con HEAD. Archive es un snapshot para soltar, no para commitear.

Contrato: git archive --format=tar.gz --prefix=<name>/ -o <file> <tree-ish> [-- <path>…]. Cero stdout. Cero --remote. Cero prefix sin /. Cero --add-virtual-file.

Qué hace (y qué no)

El man: Creates an archive of the specified format containing the tree structure for the named tree, and writes it out to the standard output. Sin --format y sin -o con extensión conocida, el formato es tar. Con -o foo.zip infiere zip. --list imprime los backends: verificado tar, tgz, tar.gz, zip.

Un commit o tag pone el committer time en cada entrada y, en tar, el commit ID en un pax header (git get-tar-commit-id). Un tree SHA usa la hora actual (o --mtime). El working tree no entra: untracked, .env local y edits sucios quedan fuera.

Sin <path>, el man dice que incluye all files and subdirectories of the current working directory. Verificado: desde src/ sin pathspec, el tar solo tiene a.ts. Un agente que cd a un subdir y corre git archive HEAD no empaqueta el repo.

Verificado 2026-09-06 (Git 2.50.1 / Apple Git-155). Repo README.md, src/a.ts, docs/c.md, .env untracked, src/untracked.ts:

  • git archive sin args: 129, usage.
  • git archive --list: 0. tar / tgz / tar.gz / zip.
  • git archive HEAD: 0. Entra README.md, docs/, docs/c.md, src/, src/a.ts. No entra untracked ni .env.
  • Working tree sucio (dirty en README.md): el tar de HEAD -- README.md sigue siendo hello\n. Archive lee el tree, no el disco.
  • --format=zip HEAD -- src: solo src/ + src/a.ts.
  • --prefix=app/ HEAD: paths app/README.md, app/src/a.ts, …
  • --prefix=app sin slash: app.gitattributes, appdocs/, appsrc/. Concatena. El tar queda ilegible.
  • --format=foo: 128, Unknown archive format 'foo'.
  • git archive nosuch: 128, not a valid object name.
  • HEAD -- does/not/exist y HEAD -- '*.nope': 128, pathspec … did not match any files.
  • Fuera de un repo: 128.
  • --remote=origin sin remote: 1, upload-archive: archiver died.
  • --remote=<path local del mismo repo>: 0. El canal existe; un agente no lo usa para “bajar el monorepo”.
  • export-ignore en .gitattributes commiteado (*.md): el tar omite README.md y docs/c.md. Default: attrs del tree, no del working tree.
  • --worktree-attributes con .gitattributes sucio (src/ export-ignore): omite src/, no aplica el *.md commiteado. Pisas el tree a ciegas.
  • --add-file=extra.txt HEAD -- README.md: 0. Entra el untracked extra.txt (basename) más el path pedido.
  • --prefix=build/ --add-file=extra.txt --prefix= HEAD: el extra queda en build/extra.txt; el tree sin prefix. Es el ejemplo del man.
  • --add-virtual-file=virtual.txt:hello: 0. El contenido va en argv. Límites de plataforma; el man manda --add-file para casos no triviales.
  • -o latest.zip HEAD: infiere zip. -v lista paths en stderr.
  • git archive --format=tar HEAD | git get-tar-commit-id: 0, SHA del commit.
  • tracked.env commiteado: entra. Archive no es check-ignore. Si el secreto está tracked, el tar lo lleva.

HEAD entra al tar; untracked, .env local y el working tree sucio no

Lo que el agente sí / no corre

QuieroComandoTrampa
Snapshot de HEADgit archive --format=tar.gz --prefix=app/ -o app.tar.gz HEADstdout al modelo / tar a /tmp sin -o
Solo un dir… HEAD -- srccd src && git archive HEAD (el cwd recorta)
Tag de release… -o v1.2.0.tar.gz v1.2.0tree SHA si quieres el pax header del commit
Excluir generatedexport-ignore en el tree (gitattributes)--worktree-attributes “para probar”
Sesión de códigoworktree / clonearchive “y ya codeo encima”

Prohibido en autónomo:

  • Stdout sin -o. El tar es binario. No lo vuelques al contexto.
  • --remote / --exec. El man: el remoto restringe qué <tree-ish> acepta (git-upload-archive). Un agente no pide el árbol por SSH “porque es más liviano que clone”.
  • --prefix sin /. Verificado: pega el string al path.
  • --add-virtual-file con secretos o payloads. El man: platform-dependent command-line limits.
  • --add-file de .env, credenciales o node_modules. El basename entra al tar aunque sea untracked.
  • --worktree-attributes para “arreglar” un tree. Cambia qué sale respecto del commit que estás empaquetando.
  • Tratar archive como clone. No hay remoto, no hay historial, no hay ls-files del índice vivo.
  • Formato inventado. Verificado: 128.
  • Pathspec que no matchea. Verificado: 128. No reintentes con globs de shell.
  • Correrlo fuera de un repo. Verificado: 128.

Receta (60 segundos)

Solo si un humano pidió un tarball/zip de un tree. Si el ticket es “otra sesión de código”: worktree. Si es “copia del repo”: clone.

git status -sb
git archive --format=tar.gz --prefix=app/ -o /tmp/app.tar.gz HEAD
tar -tzf /tmp/app.tar.gz | head
  • 0 + lista con el prefix: reporta la ruta del archivo y para. No commitees el tar.
  • Path concreto: añade -- src (u otro pathspec tracked).
  • Otro: error. No reintentes con --remote, prefix sin slash ni --add-virtual-file.

Cierre = el archivo en disco + tar -tzf / unzip -l. Cero push a main. Cero extraer encima del worktree de trabajo.

--prefix=app/ deja app/…; sin slash concatena y el tar queda ilegible

archive vs clone vs attributes

clone copia el repo. Archive exporta un tree. El tar no sirve para git status.

export-ignore / export-subst viven en gitattributes. Default: el .gitattributes del tree que archivas. --worktree-attributes lee el checkout. Para ver el attr de un path: check-attr.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. Archive no es sandbox ni backup de estado: es un snapshot de tracked (más lo que metas con --add-file).