Ramas de Git: intuición y realidad
(jvns.ca)- Mucha gente piensa que la forma en que funcionan las ramas de Git no es intuitiva.
- Se explica la diferencia entre el modelo intuitivo general sobre las ramas de Git y cómo se representan realmente las ramas dentro de Git.
- Se muestra que el modelo intuitivo y la forma en que Git realmente funciona están, de hecho, muy estrechamente relacionados.
- Se discuten las limitaciones del modelo intuitivo y por qué puede causar problemas.
Modelo intuitivo de las ramas
- Mucha gente piensa en las ramas como si fueran las ramas de un árbol de manzanas.
- En Git, las ramas no tienen un concepto de "padre", y eso es distinto de pensar que surgieron como una bifurcación desde
main.
En Git, una rama es todo el historial
- En Git, una rama no es simplemente el commit donde se bifurcó, sino que incluye el historial completo de todos los commits anteriores.
- A través de un repositorio de ejemplo, se muestra que tanto
maincomomybranchtienen 4 commits.
Las ramas se almacenan como IDs de commit
- Dentro de Git, las ramas se almacenan como pequeños archivos de texto que contienen un ID de commit.
- El commit más reciente de cada rama queda registrado en ese archivo.
- Como no existe una relación padre-hijo entre ramas, Git no conoce la relación entre ellas.
La intuición de la gente normalmente no está tan equivocada
- Decir que la intuición de la gente sobre Git está "equivocada" es, en cierto sentido, algo absurdo.
- Incluso un modelo "incorrecto" puede ser útil en la práctica.
Rebase usa el concepto "intuitivo" de rama
- Rebase vuelve a aplicar sobre
mainúnicamente los commits de la rama "intuitiva". - El resultado de rebase coincide con el modelo intuitivo.
Merge también usa el concepto "intuitivo" de rama
- Merge no copia commits, pero sí necesita un commit base compartido.
- La merge base encuentra el commit donde se bifurcó la rama según el modelo intuitivo.
Los pull requests de GitHub también usan la idea intuitiva
- Si en GitHub creas un pull request para fusionar
mybranchenmain, solo se muestran los commits de la rama intuitiva.
La intuición es buena, pero tiene límites
- La definición intuitiva de rama encaja bien con el trabajo real en Git, pero Git no puede reconocer de forma distinta una rama bifurcada desde
main.
El tronco y las ramas bifurcadas
- La gente percibe
mainymybranchde manera diferente, y eso influye en cómo usa Git. - Git no distingue si una rama es una "bifurcación" de otra.
Git puede hacer rebase "al revés"
- Como Git no sabe si una rama es una "bifurcación" de otra, el usuario debe saber cuándo y sobre qué rama hacer rebase.
- Tanto
git rebase maincomo el rebase inversogit rebase mybranchson posibles. Lo mismo ocurre con merge.
La ausencia de una jerarquía entre ramas en Git es algo extraña
- Decir que la rama
mainno es especial surge de que Git no reconoce las relaciones entre ramas. - Sí existe una relación entre las ramas, pero Git no sabe nada al respecto.
La UI de ramas de Git también es extraña
- Cuando quieres ver solo los commits "bifurcados", la forma de usar
git logygit diffes distinta.
En GitHub, la rama predeterminada sí es especial
- GitHub tiene una "rama predeterminada", y esta cumple un papel especial.
Opinión de GN⁺
Lo más importante de este texto es entender la diferencia entre la comprensión intuitiva que tiene la gente sobre las ramas de Git y la forma en que Git realmente funciona. Este artículo ayudará a ingenieros de software principiantes a entender mejor el concepto de ramas en Git y a usarlas de manera más efectiva. Ver cómo el modelo intuitivo de las ramas coincide con el trabajo real y cómo Git no maneja las relaciones entre ramas resulta interesante y útil.
1 comentarios
Comentarios en Hacker News
git reset --hardygit stash. Para deshacer un merge incorrecto, usogit reset --hard <último commit antes del merge>, y para aplicar pequeños cambios de una rama local a la rama principal, usogit stash, luego hago checkout a la rama principal y ejecutogit stash apply.git addygit commit. Este tutorial visualiza las ramas y ayuda a leerlas.git merge my-branchfusiona my-branch en la rama actual, ygit rebase my-branchhace rebase de la rama actual sobre my-branch.main.git range-diff. Esta herramienta compara dos rangos, comomain..previousymain..current.