Guía9 min

git bundle para coding agents: objetos y refs, no un tar

Resumen

git bundle mueve objetos y refs en un archivo. create + ref con nombre. verify. Cero stdout. Cero SHA suelto. Cero push al bundle. No es clone ni archive. Git 2.50.1.

GitHub
Un archivo bundle lleva refs y objetos; el working tree sucio y untracked 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 bundle empaqueta objetos y refs en un archivo para transferirlos sin servidor. El man (git-bundle(1); git-scm.com/docs/git-bundle HTTP 200, last-modified 2026-08-31; pie del man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155): Move objects and refs by archive. SYNOPSIS: git bundle create [-q | --quiet | --progress] [--version=<version>] <file> <git-rev-list-args> / verify / list-heads / unbundle.

No es clone. Clone habla con un remoto y deja un checkout. Bundle es el medio: un .pack con header de refs. Tampoco es un tar del tree: el clone desde el bundle deja .git. El man: There’s no corresponding "write" support, i.e. a git push into a bundle is not supported.

Contrato: git bundle create <file> <ref>. verify. Cero - (stdout). Cero SHA suelto. Cero unbundle autónomo. Cero push al archivo.

Qué hace (y qué no)

El man: Bundles are used for the "offline" transfer of Git objects without an active "server". clone, fetch y ls-remote leen un bundle. Push no.

Revisions must be accompanied by reference names to be packaged in a bundle. Alternatively --all can be used. Un SHA no es un nombre de ref. --all empaqueta todas las refs, no el índice, el working tree, el stash, la config ni los hooks.

Un rango old..new crea un bundle con prerequisite: el destino ya tiene que tener old. verify lo comprueba. Un bundle sin prerequisite (complete history) se clona en vacío.

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

  • git bundle: 129, need a subcommand.
  • git bundle create: 129, need a <file> argument.
  • git bundle create repo.bundle: 128, Refusing to create empty bundle.
  • git bundle create head.bundle <SHA de HEAD>: 128, empty bundle. El man: un SHA suelto no es ref.
  • git bundle create headname.bundle HEAD: 0.
  • git bundle create main.bundle main: 0.
  • --all: 0. list-heads = refs/heads/main + HEAD.
  • main~1..main: 0. verify: The bundle requires this ref: el SHA de main~1.
  • <SHA>..<SHA>: 128, empty bundle. Mismo caso que el SHA suelto.
  • verify main.bundle: 0. complete history. hash algorithm: sha1.
  • list-heads main.bundle: SHA + refs/heads/main.
  • git ls-remote main.bundle: 0, misma ref.
  • git bundle create - main: 0. El bundle va a stdout (binario).
  • unbundle main.bundle: 0. Plumbing. El man: intended to be called only by git fetch.
  • Fuera de un repo: 128, Need a repository to create a bundle.
  • Subcomando inventado: 129, unknown subcommand.
  • create x.bundle nosuch: 128, unknown revision.
  • git clone main.bundle cloned: 0. Checkout de main. README.md = hello\\n (el tree). No entra untracked ni el dirty.
  • verify del incremental en un repo vacío: 1, Repository lacks these prerequisite commits.
  • git clone incr.bundle: 128, remote transport reported error.
  • git push main.bundle main: 1, failed to push some refs. El man lo prohíbe.
  • lastbundle..main (tag en el corte): 0. Incremental con prerequisite = el tag.

create pide un nombre de ref; un SHA suelto o un rango SHA..SHA sale empty bundle

Lo que el agente sí / no corre

QuieroComandoTrampa
Backup de refsgit bundle create backup.bundle --allcp -r .git (el man lo desaconseja)
Snapshot de maingit bundle create main.bundle mainSHA de HEAD “porque es lo mismo”
¿Aplica aquí?git bundle verify file.bundleunbundle a ciegas
¿Qué refs trae?git bundle list-heads file.bundle / ls-remotefile / tar -tf
Otro checkoutclone del bundle a un pathunbundle en el repo de trabajo
Sesión extraworktreebundle “y ya codeo encima”

Prohibido en autónomo:

  • Stdout (<file> = -). El bundle es binario. No lo vuelques al contexto.
  • SHA suelto o <SHA>..<SHA>. Verificado: 128, empty bundle.
  • unbundle. El man lo reserva a fetch. Un agente clona o fetchea el archivo.
  • git push al bundle. Verificado: 1. No hay write.
  • Incremental (old..new) sin verify en el destino. Verificado: clone 128 si falta el prerequisite.
  • Tratar bundle como tar del working tree. Untracked, dirty y stash no entran. El man: will not help you backup contents of the index, working tree, the stash, per-repository configuration, hooks, etc.
  • --all como “copia del disco”. Solo refs.
  • Correrlo fuera de un repo. Verificado: 128.
  • Path que no es ref. Verificado: 128.

Receta (60 segundos)

Solo si un humano pidió mover el repo sin red (USB, air-gap, backup de refs). Si el ticket es “otra sesión de código”: worktree. Si es “copia con remoto”: clone.

git status -sb
git bundle create /tmp/repo.bundle --all
git bundle verify /tmp/repo.bundle
git bundle list-heads /tmp/repo.bundle
  • 0 + complete history + lista de refs: reporta la ruta y para. No commitees el .bundle.
  • Incremental: git bundle create /tmp/incr.bundle <tag>..main y el destino corre verify antes de fetch/clone.
  • Otro: error. No reintentes con SHA, - ni unbundle.

Cierre = el archivo en disco + verify + list-heads. Cero push a main. Cero extraer encima del worktree de trabajo.

verify OK pide complete history o el prerequisite en el destino; sin él clone sale 128

bundle vs clone vs fetch

clone crea un directorio. Puede clonar desde un bundle (git clone file.bundle dest). El destino queda con remote.origin.url apuntando al archivo.

fetch lee el bundle como si fuera un remoto. ls-remote lista las refs del archivo. push no escribe en él.

El rango de create es el de rev-list, pero el lado derecho tiene que resolverse a una ref (el man: a revision name or a range whose right-hand-side cannot be resolved to a reference is not accepted). Un tag de corte (-f lastbundle) es el ejemplo del man para incrementales.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. Bundle no es sandbox ni backup de estado local: es refs + objetos alcanzables.