Sincronizar un fork de Git con upstream: 3 métodos seguros
Sincronizar un fork de Git con upstream de 3 formas: pull de dos comandos, rebase para historial limpio, botón de GitHub y arreglos si no sincroniza.
TL;DR: ejecuta git fetch upstream && git merge upstream/main && git push origin main y tu fork queda al día. Ese es el flujo completo de «git sync fork with upstream» en una línea — traer los cambios del proyecto que forkeaste y empujarlos a tu copia. Si prefieres historial lineal, cambia el merge por git rebase upstream/main y haz force-push. Y si nunca configuraste el remoto upstream, empieza por el paso 1 de abajo, porque ese remoto ausente es la razón número uno por la que un fork «no sincroniza». Todo lo demás — rebase, el botón de sync de GitHub, ramas divergidas que no se dejan empujar — es detalle encima de esos tres comandos.
¿Qué significa sincronizar un fork con upstream?
Un fork es tu copia del repositorio de otra persona en GitHub. El original es el upstream; tu copia es el origin. Los forks de GitHub no se actualizan solos — cuando los maintainers fusionan un pull request, tu copia se queda con el código de ayer. Sincronizar un fork significa traer los commits nuevos del upstream a tu fork para que tu rama coincida —o al menos contenga— el estado actual del proyecto.
Esto importa por dos razones. Primero, las contribuciones: cada pull request que abres desde un fork desactualizado lleva ruido extra, y los maintainers te pedirán actualizar antes de fusionar. Segundo, el autohospedaje o el estudio: si corres un fork en producción o simplemente lees el código, un fork con un mes de atraso es un mes de correcciones de bugs que no tienes.
¿Cómo sincronizo un fork con upstream desde la terminal?
Tres pasos: declarar el upstream una vez, hacer fetch de él, y después merge y push. El cableado es permanente — los pasos 2 y 3 son todo lo que escribes la próxima vez.
Paso 1 — agrega el remoto upstream (una vez por clon).
# dentro de tu clon local del fork
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
git remote -v # confirma: origin -> tu fork, upstream -> el original
La URL correcta está en la página del repo original: el botón verde Code. Un error común es apuntar ambos remotos a tu fork — entonces un «sync» no hace nada en silencio, porque hiciste fetch de una copia tan desactualizada como la que ya tienes.
Paso 2 — haz fetch y merge de la rama upstream.
git checkout main
git fetch upstream
git merge upstream/main
git push origin main
Esa es la respuesta estándar a «git sync fork with upstream command line». Un fast-forward es el resultado normal — el main de tu fork no tenía nada nuevo, así que simplemente se desliza hacia upstream/main y no se crea ningún commit de merge.
Paso 3 — repite a demanda. No hay nada más que memorizar más allá de git fetch upstream && git merge upstream/main && git push origin main. Para ver qué tanto atraso llevas antes del merge, corre git rev-list --count main..upstream/main después del fetch.
¿Rebase o merge al sincronizar un fork?
Ambos dejan el mismo código en tu fork; difieren en el historial que dejan atrás. Elige una política por repo y respétala:
| Método | Comando | Resultado en el historial | Ideal para |
|---|---|---|---|
| Merge | git merge upstream/main |
Commit de merge extra en ramas divergidas | Ramas de feature con PRs abiertos — nunca reescribe nada |
| Rebase | git rebase upstream/main |
Tus commits re-reproducidos encima, historial lineal | Mantener el main de tu fork limpio; forks divergidos que quieres resetear |
| UI de GitHub | Botón Sync branch / merge de PR | Igual que merge | Ponerse al día rápido sin abrir un clon |
La variante con rebase del sync:
git fetch upstream
git rebase upstream/main
git push --force-with-lease origin main
El force push es obligatorio porque el rebase reescribe los IDs de los commits — la rama remota de tu fork ya no desciende de la local. Prefiere siempre --force-with-lease antes que --force: se niega a sobrescribir el remoto si alguien (u otra máquina tuya) publicó mientras tanto, lo que vuelve seguro por defecto al comando peligroso.
Una regla que vale tatuar: nunca hagas rebase de una rama con un pull request abierto a menos que sepas lo que estás haciendo — el rebase cambia los IDs de los commits, y eso puede desconectar un PR abierto de sus commits. Sincroniza main con merge (o rebaséalo antes de empezar trabajo nuevo) y mantén las ramas de PR fuera del asunto.
¿Por qué mi fork no sincroniza con upstream?
Los cuatro sospechosos de siempre, en el orden en que aparecen en terminales reales:
- No existe el remoto
upstream—git remote -vmuestra soloorigin. Síntoma:git fetch upstreamfalla con'upstream' does not appear to be a git repository. Arreglo: paso 1 de arriba. - Hiciste fetch pero nunca merge — el fetch actualiza
upstream/mainen tu repo local pero no toca ninguna rama de trabajo. Síntoma:git logse ve viejo después de un fetch exitoso. Arreglo:git merge upstream/main. - Historial divergido — hiciste commits en el
mainde tu fork, y el upstream también avanzó.git pullentonces se queja de historiales no relacionados o fuerza un merge. Arreglo, si quieres que gane el upstream:git reset --hard upstream/main(tira a la basura tus commits exclusivos del main local — revisagit stash listo respalda con una rama primero; si el reset malo ya ocurrió, el camino de recuperación es el mismo que en git undo last commit:git reflogtodavía sabe dónde estaba la punta vieja). - Push rechazado como non-fast-forward después de un rebase — rebasteaste pero empujaste normal. Arreglo:
git push --force-with-lease origin main.
Un quinto caso, raro: el repo upstream fue renombrado o borrado, así que hasta la URL del paso 1 da 404. GitHub redirige los repos renombrados, así que un fallo rotundo suele significar borrado o hecho privado — no hay nada con qué sincronizar.
¿Se puede sincronizar un fork desde la web de GitHub?
Sí. En la página de tu fork, el selector de ramas muestra un botón Sync fork cada vez que tu rama va atrás; un clic trae el upstream. Debajo del doblez, lo mismo funciona como pull request: abre un PR desde upstream/main hacia el main de tu fork y fusiona.
Los límites del botón explican cuándo volver a la terminal: solo hace fast-forward o merge — no rebase, y se niega de plano cuando las ramas han divergido, diciéndote que descartes commits o uses la línea de comandos. También sincroniza únicamente la rama por defecto. Para todo lo que pase de una puesta al día simple, los tres comandos de arriba son la herramienta.
¿Con qué frecuencia conviene sincronizar tu fork?
Antes de cada trabajo nuevo es la respuesta honesta: rama desde un main fresco, y ningún PR que abras empieza con «esto está basado en una versión de hace tres semanas». Para forks a los que contribuyes activamente, un sync diario o por sesión de main cuesta segundos. Para un fork que solo lees o despliegas, sincroniza cuando el upstream publique algo que quieras — suscríbete al feed de releases del repo original y sincroniza en cada release. Sincronizar es barato precisamente porque es rutina; un fork con seis meses de atraso suele necesitar cirugía en vez de un merge, y así es como «sincroniza mi fork» se convierte en una tarde entera.
Chuleta de comandos
# configuración de una sola vez
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
# sync de rutina (política merge)
git fetch upstream && git merge upstream/main && git push origin main
# sync de rutina (política rebase, historial lineal)
git fetch upstream && git rebase upstream/main && git push --force-with-lease origin main
# ¿qué tan atrás voy?
git fetch upstream && git rev-list --count main..upstream/main
# divergido sin remedio — dejar main idéntico al upstream (destructivo)
git fetch upstream && git reset --hard upstream/main && git push --force-with-lease origin main
Guarda el par de líneas de rutina en la memoria muscular y el fork divergido seguirá siendo una curiosidad que lees, no un problema que arreglas. Si tu aseo de git llega hasta los servidores, la chuleta de journalctl cubre la otra mitad de mantener legible el historial de una máquina.