Guía9 min

git push para coding agents: origin, tu rama, cero main

Resumen

git push actualiza refs remotos y envía los objetos que el remoto aún no tiene. Un agente nombra origin y su rama de trabajo; no main, no --force, no --delete, no --tags, no --no-verify. Si Git rechaza un non-fast-forward, fetch primero. Git 2.50.1.

GitHub
Push fast-forward de una rama de agente hacia origin; main no se toca

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 push no es “sube esto a main”. El man (git-push(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-push HTTP 200, man 2.55.0): actualiza uno o más refs en un remoto y envía los objetos que el remoto todavía no tiene. Lo más simple: git push <remote> <branch>. El <repository> por default es el upstream de la rama actual, o origin si no hay.

GitHub Docs (HTTP 200, 2026-09-04, Pushing commits to a remote repository): el comando toma dos argumentos — un remote (origin) y una rama (main en su ejemplo). Un coding agent no usa ese ejemplo: cierra con PR, no con push a la default. Force, lease y amend viven en force-push. Aquí el contrato: qué forma corre un agente, qué flags están prohibidos, y qué hacer cuando Git rechaza.

Fast-forward o nada

PUSH RULES del man: destino refs/heads/* → solo fast-forward (el remoto es ancestro del commit que empujas; el source es un commit). Destino refs/tags/*cualquier update se rechaza. --force o un + delante del refspec saltan esas reglas; no convierten un blob en rama, y no vencen receive.denyNonFastForwards ni un hook que niegue.

GitHub Docs, Dealing with "non-fast-forward" errors: si tu copia está detrás, el remoto rechaza. Hay que fetch antes de volver a empujar. Un agente no traduce ese rechazo en -f.

git push origin HEAD          # misma rama, fast-forward
git push -u origin HEAD       # primer push: fija upstream
git push --dry-run origin HEAD

push.default default = simple: empuja una rama del mismo nombre. Sin upstream, git push a secas puede fallar. El agente nombra remote y ref (origin HEAD o origin <rama>), no adivina matching.

origin recibe el tip de la rama del agente; main no se actualiza

Lo que el agente sí / no corre

QuieroComandoTrampa
Primer push de la ramagit push -u origin HEADgit push sin remote/ref; origin main
Push siguientegit push origin HEAD-f “porque ya existe”
Ver qué haríagit push --dry-run origin HEADConfiar en el long de status
Parseargit push --porcelain origin HEADParsear stderr humano
Cerrar trabajogh pr createPush a main

Prohibido en autónomo:

  • git push origin main / master / la default del repo. El destino es la rama de trabajo. Branch protection no es un permiso para probar.
  • --force / -f / +<refspec>. El man: desactiva el chequeo de ancestro, las PUSH RULES y --force-with-lease; puede hacer que el remoto pierda commits. --force aplica a todos los refs que el comando empuja. Detalle y lease: force-push.
  • --delete / -d / git push origin :rama. El man y GitHub Docs: <src> vacío borra <dst> en el remoto (git push origin :dev). Un agente no borra refs ajenos.
  • --tags / --all / --branches / --mirror / --prune. --tags empuja todo refs/tags. --all todas las ramas. --mirror force-updatea y borra en el remoto. --prune borra en el remoto lo que ya no existe en local.
  • --no-verify. El default es --verify: el hook pre-push puede abortar. Saltar el hook es eludir el repo.
  • URL suelta como <repository>. Nombra el remote de git remote -v (origin, a veces el fork). SECURITY del man: fetch/push no impiden que un peer robe objetos no pensados para compartir. Namespaces en el servidor no son ACL de lectura.
  • Refspec : / +: (matching). Empuja cada rama local que ya existe en el remoto.
  • --follow-tags “por si acaso”. Empuja tags anotados alcanzables. Un agente no publica tags.
  • Destino distinto al nombre local (HEAD:main, topic:main). GitHub Docs, Renaming branches: git push REMOTE LOCAL:REMOTE renombra en el remoto. Eso es un push a otra rama, no un rename local.

Receta (60 segundos)

Solo en un worktree propio:

git status -sb                       # limpio; no MERGE_HEAD / rebase
git branch --show-current            # no main, no master
git fetch origin
git push -u origin HEAD              # o sin -u si ya hay upstream

Si el push se niega con non-fast-forward / rejected (flag ! en OUTPUT): no -f. Fetch, mira HEAD..origin/<rama>, integra con merge/--ff-only o reporta divergencia. Luego push otra vez, sin flags.

GitHub Docs, Resolving blocked commits: push protection puede bloquear un push si el commit trae un secreto soportado. Quita el secreto del historial o sigue la URL de bypass que da GitHub. Un agente no bypasea protección de secretos.

Cierre: PR, no merge a main.

Git rechaza non-fast-forward; el siguiente paso es fetch, no --force

Output, forks y el servidor

El man (OUTPUT, protocolo Git/ssh): <flag> <summary> <from> -> <to> (<reason>). --porcelain: <flag> \\t <from>:<to> \\t <summary> (<reason>) a stdout. Flags: espacio = fast-forward; + = forced update; - = borrado; * = ref nuevo; ! = rechazado; = = ya al día. Un agente que parsea usa porcelain, no la tabla humana.

rejected = Git ni intentó enviar (típico: no es fast-forward y no forzaste). remote rejected = el remoto dijo no: hook, receive.denyCurrentBranch, receive.denyNonFastForwards, receive.denyDeletes. remote failure = error transitorio. Reporta el reason; no reintentes con más flags.

Forks (GitHub Docs, Remotes and forks): git remote add upstream <url> y git fetch upstream. El push del agente va a su origin (el fork), no a upstream. El PR es el puente.

--set-upstream / -u: para cada rama que quedó al día o se empujó bien, fija tracking. Sirve en el primer push de la rama de trabajo. No es un permiso para empujar main.

push.autoSetupRemote=true asume -u en el push default sin upstream. Un agente igual pasa remote y ref explícitos: no depende de un config local que el humano puede no tener.

Checklist

  • Worktree propio. git status -sb limpio. Rama ≠ main/master.
  • git fetch origin antes si el último fetch no es de esta receta.
  • git push -u origin HEAD (o sin -u si ya hay upstream). Cero URL suelta.
  • Cero --force, +refspec, --delete, :rama, --tags, --all, --mirror, --prune, --no-verify.
  • ! / non-fast-forward → fetch + reportar, no -f.
  • Push protection / secreto → no bypass. Quita el secreto o para.
  • Cierre = PR, no push a la default.

FAQ

¿git push sin argumentos? Depende de push.default y de si hay upstream. El man: puede fallar. Nombra origin y HEAD.

¿git push origin main “solo esta vez”? No. GitHub Docs usa main como ejemplo de argumentos, no como política de un agente. Default = PR.

¿--force-with-lease en vez de --force? Sigue siendo force. El man avisa que sin <expect> un git fetch de fondo derrota el lease. Guía: force-push.

¿Puedo borrar la rama remota al cerrar el PR? git push origin :rama borra. En autónomo, no. gh pr merge / borrar rama es decisión humana o del host tras el merge.

¿--tags para no olvidar un tag? El man: empuja todos los tags. Un agente no publica tags.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. Push no es pull ni fetch: empuja refs; no integra.

Verificado 2026-09-04 contra git-push(1) (Git 2.50.1 / Apple Git-155), git-scm.com/docs/git-push (HTTP 200, man 2.55.0) y GitHub Docs “Pushing commits to a remote repository” (HTTP 200).