Guía10 min

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.

GitHub
Commits A B C de topic reaplicados como A' B' C' sobre el tip de master

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.

Rebase reescribe SHA; merge añade un commit de fusión

Lo que el agente sí / no corre

QuieroComandoTrampa
Actualizar mi topic no pusheado sobre origin/maingit fetch origin && git rebase origin/mainSin fetch, rebaseas un main viejo
Parar a mitadgit rebase --abort--quit no resetea HEAD al original
Saltar el parche que chocagit rebase --skipPierdes ese commit. No es “resolver”
Seguir tras resolvergit rebase --continueSolo después de git add paths explícitos
Historia compartida / PR abiertomerge + commit nuevo, o pedir al humanoRebase + force reescribe el remoto

Prohibido en autónomo:

  • git rebase -i / --interactive / --edit-todo. Abren editor. GitHub lista pick/reword/edit/squash/fixup/exec; un harness headless no es ese flujo.
  • git rebase en main o 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 --force o 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 hook pre-rebase. El default es --verify.
  • git rebase sin <upstream> en detached HEAD o sin upstream configurado: aborta. Nombra origin/main.
  • Resolver conflictos reescribiendo archivos ajenos al ticket. --abort y 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}).

--abort vuelve al tip original; -i abre editor

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, --exec ni --root salvo orden escrita.
  • Fetch primero. Upstream explícito (origin/main), no el default mudo.
  • Rama no compartida. status -sb no dice que otros ya la tienen.
  • Conflicto → --abort o paths del conflicto. Cero --skip por default.
  • Cero force al remoto. Cero --update-refs.
  • --abort si no es tu worktree o si el reset --hard interno 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).