git rebase para coding agents: reescribe SHA; no es merge ni reset
Resumen
git rebase reaplica commits sobre otra base. Equivale a reset --hard del tip y luego cherry-pick uno a uno. Un agente no corre -i, no rebasea ramas compartidas y no empuja el resultado con --force. Man git-rebase y docs de GitHub.

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 rebase reaplica los commits de la rama actual que no están en <upstream> sobre otra base. El man (Git 2.50.1 / Apple Git-155): primero guarda upstream..HEAD, luego hace el mismo efecto que git reset --hard <upstream> (o --onto <newbase>), y reaplica uno a uno. Los SHA cambian. No es un merge (no crea un commit de fusión) y no es reset de un archivo.
GitHub Docs (2026): “it's considered bad practice to rebase commits when you've already pushed to a repository.” Un coding agent que “limpia el historial” con rebase -i + force push reescribe lo que ya vieron CI y reviewers.
Esta guía no sustituye worktrees ni PRs con gh. El contrato: cuándo un agente puede rebasear, qué flags están prohibidos, y cómo abortar.
Qué hace, en el diagrama oficial
Con topic = A—B—C encima de E, y master = D—E—F—G:
git rebase master
git rebase master topic # switch a topic y luego rebase master
quedan A'—B'—C' sobre G. El man: la segunda forma es git switch topic + git rebase master.
Si un commit de topic introduce el mismo texto que algo en HEAD..<upstream>, se omite (patch ya aceptado upstream con otro mensaje o timestamp).
--onto transplanta: git rebase --onto master next topic finge que topic nació de master y no de next.

Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
Actualizar mi topic no pusheado sobre origin/main | git fetch origin && git rebase origin/main | Sin fetch, rebaseas un main viejo |
| Parar a mitad | git rebase --abort | --quit no resetea HEAD al original |
| Saltar el parche que choca | git rebase --skip | Pierdes ese commit. No es “resolver” |
| Seguir tras resolver | git rebase --continue | Solo después de git add paths explícitos |
| Historia compartida / PR abierto | merge + commit nuevo, o pedir al humano | Rebase + force reescribe el remoto |
Prohibido en autónomo:
git rebase -i/--interactive/--edit-todo. Abren editor. GitHub listapick/reword/edit/squash/fixup/exec; un harness headless no es ese flujo.git rebaseenmaino en una rama ya pusheada. El man, NOTES: “You should understand the implications of using git rebase on a repository that you share.” Recuperar downstream es un ripple: “anyone downstream of it is forced to manually fix their history.”- Empujar el resultado con
--forceo amend+force. Eso es otra guía; rebase solo reescribe local. --update-refs: “Automatically force-update any branches that point to commits that are being rebased.” No toca worktrees checked-out, pero sí otras refs locales. Un agente no lo añade.--no-verify: salta el hookpre-rebase. El default es--verify.git rebasesin<upstream>en detached HEAD o sin upstream configurado: aborta. Nombraorigin/main.- Resolver conflictos reescribiendo archivos ajenos al ticket.
--aborty reporta.
El reset interno es --hard. Untracked puede pisarse igual que en reset. No rebasees el checkout del humano.
Receta (60 segundos)
Solo en un worktree propio, rama no publicada o “ahead” solo con commits tuyos:
git status -sb
git fetch origin
git rebase origin/main
Conflicto:
git status
# resuelve SOLO los paths del conflicto, o:
git rebase --abort
--abort: “reset HEAD to the original branch.” Si arrancaste con <branch>, HEAD vuelve a esa rama.
--continue tras git add src/foo.ts. No git add ..
--skip solo si el parche es un cherry-pick vacío que el humano pidió tirar. Default --empty=drop ya tira commits que quedan vacíos; no improvises skip.
ORIG_HEAD apunta al tip antes del reset interno. El man avisa: otros git reset durante el rebase pueden pisarlo. El tip previo sigue en el reflog (@{1}).

Rebase vs merge vs reset
- merge: commit nuevo, historia hacia adelante. Eso va a un PR. No reescribe SHA publicados.
- reset: mueve HEAD (y según modo, index/disco). No reaplica una serie. Ver git reset.
- rebase: nueva serie de commits. Misma receta de “actualizar main” que mucha gente usa a mano; en un agente es opt-in y local.
Si el PR ya existe, el default del agente es merge origin/main en la rama + push normal. Rebase del PR = force del remoto. GitHub lo marca mala práctica una vez pusheado.
Upstream rebaseado por otro: sección RECOVERING FROM UPSTREAM REBASE del man. Caso fácil: git rebase subsystem salta patch-ids iguales. Caso difícil (conflictos, -i, amend, filter-repo): no lo “arregla” un agente; aborta.
Checklist
- El agente no corre
-i,--edit-todo,--execni--rootsalvo orden escrita. - Fetch primero. Upstream explícito (
origin/main), no el default mudo. - Rama no compartida.
status -sbno dice que otros ya la tienen. - Conflicto →
--aborto paths del conflicto. Cero--skippor default. - Cero force al remoto. Cero
--update-refs. -
--abortsi no es tu worktree o si el reset--hardinterno asusta. - Historia publicada: merge + PR.
FAQ
¿git rebase sin args? Usa branch.<name>.remote + merge y asume --fork-point. Sin upstream configurado, aborta. Un agente nombra el commit.
¿--keep-base? Reaplica sobre el merge-base, no sobre el tip de upstream. Incompatible con --onto y --root. No es el default de “actualizar main”.
¿Commits vacíos? --empty=drop (default) tira los que quedan vacíos. Los que empiezan vacíos se conservan salvo --no-keep-empty. -i implica stop.
¿Hook pre-rebase? Corre por default. --no-verify lo salta. No lo desactives.
¿Puedo rebasear un solo archivo? No. Rebase trabaja commits. Para un path: restore o reset pathspec.
El curso instalar un agente cubre el loop local. Rebase reescribe SHA; no es sandbox.
Verificado 2026-09-03 contra git-rebase(1) (Git 2.50.1 / Apple Git-155) y GitHub Docs About Git rebase (HTTP 200).
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git status para coding agents: porcelain, XY, no el long

Reusable workflows: workflow_call, no copies el YAML entre repos

schedule (cron) en GitHub Actions: UTC, no cada minuto
