* notes / git

Git: trucos y atajos que mejoran tu día (incluido `rarara`)

Comandos, alias y patrones de git que uso a diario: add -p, commit --fixup, rarara, worktree, reflog y los errores que solo se aprenden al perder un commit y recuperarlo.

October 6, 20258 min read#git#productividad#herramientas

Hay gente que vive dentro de la interfaz de su editor y nunca ha escrito git rebase -i en una terminal, y les va bien. Pero siempre llega el momento en que algo se rompe: un merge que no querías, un commit perdido tras un reset, un historial enredado. Ahí, conocer git por dentro es la diferencia entre cinco minutos de molestia y media tarde de pánico. Esta es la lista de trucos que uso de verdad, incluido el alias más tonto y más útil de toda mi configuración: rarara.

Contexto: trabaja con git, no contra él

La fricción con git casi siempre viene de un malentendido: tratarlo como una lista de comandos memorizados (git add, git commit, git push) sin ver el modelo que hay debajo. Git es un grafo de commits inmutables, con referencias móviles (las ramas), un área de staging y un árbol de trabajo. Cuando entiendes ese modelo, los comandos dejan de ser fórmulas mágicas y se vuelven operaciones sobre una estructura.

Lo que sigue es mi caja de herramientas, agrupada por escenario.

El staging inteligente: add -p

Cuando un cambio en un archivo mezcla dos cosas distintas (por ejemplo, un fix puntual y una corrección en los comentarios), meter todo en el mismo commit es mal hábito. La solución es el staging interactivo:

git add -p archivo.ts

Git divide el diff en hunks y te pregunta, por cada uno, si lo añades (y), lo saltas (n), lo partes en trozos más pequeños (s) o lo editas a mano (e). Esa disciplina mejora los commits casi de un día para otro: cada uno hace una cosa y la describe.

La pareja commit --fixup + rebase --autosquash

Pongamos que en la revisión de una PR salen tres comentarios menores que tocan tres commits distintos. Lo torpe es añadir tres commits nuevos llamados «fix typo», «fix style», «fix logic». Lo limpio es:

git commit --fixup=<sha-del-commit-a-arreglar>
git rebase -i --autosquash main

El primer comando crea un commit con el asunto especial fixup! ...; el segundo abre el editor de rebase con los fixup ya colocados junto a sus commits destino y marcados como fixup, así que el cambio se absorbe y el mensaje se descarta. El resultado es un historial limpio, sin rastro de los parches intermedios.

Antes del autosquashABCfixup!BDfixup!Cfixup!BDespués del autosquashAB'C'D

El alias estúpido: rarara

En un momento de frustración con una rama especialmente difícil, definí esto:

[alias]
  rarara = "!git rebase --abort 2>/dev/null; git rebase --abort 2>/dev/null; git rebase --abort 2>/dev/null; true"

Es, literalmente, abortar el rebase tres veces. Nació como broma (el equivalente a «no quiero seguir, sácame de aquí»), pero sobrevivió porque cumple una función real: en un rebase enredado con submódulos, o tras un cherry-pick que dejó el árbol en un estado raro, garantiza que no quede nada vivo del intento anterior. Lo uso cuando algo va realmente mal y necesito un freno de emergencia. No es elegante, y no me importa.

git worktree: una rama por carpeta

Cuando me piden revisar una PR mientras tengo cambios a medias en mi rama, ya no uso stash: creo un worktree paralelo:

git worktree add ../proyecto-review pr-1234

Eso crea el árbol de trabajo en otra carpeta, con la rama indicada ya checked out, sin tocar mi directorio actual. Puedo abrir esa carpeta en otro editor, revisar, correr los tests y volver a lo mío sin un solo stash pop. Al terminar, git worktree remove ../proyecto-review la elimina. Si saltas entre varias ramas en una mañana, este comando te cambia el día.

git reflog: la red de seguridad invisible

El reflog registra cada movimiento de HEAD, incluso los que no produjeron commit. Si reseteo al sitio equivocado, el commit parece perdido; pero sigue ahí, sin ninguna referencia que lo apunte, y el recolector de basura no lo toca en al menos noventa días. Para recuperarlo:

git reflog                       # localiza el sha previo
git checkout -b rescate <sha>    # crea una rama nueva ahí

Saber que el reflog existe convierte muchos errores que parecen catastróficos en sustos menores.

git bisect: encontrar el culpable con búsqueda binaria

Cuando un bug aparece y nadie sabe cuándo se introdujo, git bisect automatiza la búsqueda binaria sobre el historial:

git bisect start
git bisect bad                 # commit actual está roto
git bisect good v1.4.0         # esta versión funcionaba
# git hace checkout al punto medio; pruebas; respondes:
git bisect good                # o bisect bad
# … hasta que git imprime el sha del primer commit defectuoso
git bisect reset

Si tienes un script que reproduce el fallo, puedes automatizar todo con git bisect run ./repro.sh, dejarlo trabajando y volver en unos minutos con el sha identificado.

git stash --keep-index

Si quiero correr los tests solo sobre lo que tengo en staging, sin mezclar los cambios sin preparar, git stash --keep-index esconde lo no preparado y deja el árbol de trabajo igual al staging. Después, git stash pop devuelve todo a como estaba. Es la forma limpia de comprobar que el commit que estás a punto de hacer pasa los tests por sí solo.

Configuración condicional con includeIf

Si trabajas con identidades distintas, una cuenta personal y otra del trabajo, tarde o temprano mandas commits con el correo equivocado. includeIf lo resuelve de una vez:

# ~/.gitconfig
[user]
  name = Alex
  email = alex@personal.example
 
[includeIf "gitdir:~/work/"]
  path = ~/.gitconfig-work
 
# ~/.gitconfig-work
[user]
  email = alex@empresa.example

Cualquier repositorio bajo ~/work/ usa automáticamente el correo del trabajo. Lo configuras una vez y te olvidas.

Hooks: husky, lefthook y el orden previo al push

Para forzar formato, lint y tests rápidos antes de cada commit, uso lefthook, por velocidad y porque su configuración es simple:

# lefthook.yml
pre-commit:
  parallel: true
  commands:
    lint:
      glob: "*.{ts,tsx}"
      run: pnpm eslint {staged_files}
    format:
      glob: "*.{ts,tsx,md,json}"
      run: pnpm prettier --check {staged_files}
pre-push:
  commands:
    test:
      run: pnpm vitest --run --changed

Husky hace lo mismo y es más común; lo de lefthook es preferencia personal, nada más.

Mi .gitconfig real (extracto)

[alias]
  s        = status -sb
  co       = checkout
  br       = branch
  lg       = log --graph --oneline --decorate --all
  unstage  = reset HEAD --
  amend    = commit --amend --no-edit
  fix      = "!f() { git commit --fixup=$1; }; f"
  squash   = "!git rebase -i --autosquash $(git merge-base HEAD main)"
  wip      = "!git add -A && git commit -m 'wip' --no-verify"
  unwip    = "!git log -1 --pretty=%B | grep -q '^wip$' && git reset HEAD~ || echo 'no wip on top'"
  rarara   = "!git rebase --abort 2>/dev/null; git rebase --abort 2>/dev/null; git rebase --abort 2>/dev/null; true"
 
[rerere]
  enabled = true            # recuerda resoluciones previas de conflictos
 
[pull]
  rebase = true             # evita merges de pull innecesarios
 
[push]
  default = current
  autoSetupRemote = true    # crea upstream automáticamente al pushear nueva rama
 
[diff]
  algorithm = histogram     # diffs más legibles en refactors
 
[merge]
  conflictstyle = zdiff3    # muestra base común en conflictos

rerere merece mención aparte: guarda cómo resolviste un conflicto y, si vuelve a aparecer, lo reaplica automáticamente. En un rebase largo ahorra muchísimo tiempo.

Hallazgos

  1. El historial es comunicación, no contabilidad. Cada commit debería poder leerse en voz alta y entenderse. fixup + autosquash y add -p ayudan justo a eso.
  2. Casi todo en git es reversible. reflog y worktree te dan tanto margen de maniobra que muchos miedos desaparecen.
  3. El alias más útil es el que escribes tú. No copies el mío sin entenderlo; copia la actitud: detectar la fricción y resolverla con dos líneas en tu .gitconfig.

Closure

Git tiene fama de hostil, y en parte se la ha ganado. Pero unas pocas horas entendiendo sus piezas básicas (el grafo, el staging, el reflog, los worktrees) se pagan solas durante años. Empieza por dejar add . y pasarte a add -p. Solo con eso, tu semana que viene ya será mejor. Y si todo lo demás falla… rarara.