La afirmación de que "la ramificación es gratuita en git" es una simplificación de los hechos porque no es "gratuita" per se. Mirando debajo del capó, una afirmación más correcta sería decir que la ramificación es redonkulosamente barata , porque las ramas son básicamente referencias a compromisos . Defino "baratura" aquí como menos gastos generales más barato.
Analicemos por qué Git es tan "barato" al examinar qué tipos de gastos generales tiene:
¿Cómo se implementan las ramas en git?
El repositorio de git, en .git
su mayoría , consiste en directorios con archivos que contienen metadatos que usa git. Cada vez que crea una rama en git, por ejemplo git branch {name_of_branch}
, suceden algunas cosas:
- Se crea una referencia a la sucursal local en:
.git/refs/heads/{name_of_branch}
- Se crea un registro de historial para la sucursal local en:
.git/logs/refs/heads/{name_of_branch}
Eso es básicamente todo, se crean un par de archivos de texto. Si abre la referencia como un archivo de texto, el contenido será el id-sha del commit al que apunta la rama. Tenga en cuenta que la ramificación no requiere que realice ninguna confirmación, ya que son otro tipo de objeto. Ambas ramas y commits son "ciudadanos de primera clase" en términos de git y una forma es pensar en la relación de branch-to-commit como una agregación en lugar de una composición. Si elimina una rama, las confirmaciones seguirán existiendo como "colgantes". Si eliminó accidentalmente una rama, siempre puede intentar encontrar la confirmación con git-lost-found
o git-fsck --lost-found
y crear una rama en el sha-id que encuentre colgando (y siempre que git aún no haya realizado ninguna recolección de basura).
Entonces, ¿cómo hace git un seguimiento de en qué rama estás trabajando? La respuesta es con el .git/HEAD
archivo, que se parece a esto si estás en la master
rama.
ref: refs/heads/master
Cambiar ramas simplemente cambia la referencia en el .git/HEAD
archivo, y luego procede a cambiar el contenido de su espacio de trabajo con los definidos en la confirmación.
¿Cómo se compara esto en otros sistemas de control de versiones?
En Subversion , las ramas son directorios virtuales en el repositorio . Entonces, la forma más fácil de ramificarse es hacerlo de forma remota, con una sola línea svn copy {trunk-url} {branch-url} -m "Branched it!"
. Lo que SVN hará es lo siguiente:
- Copie el directorio de origen, por ejemplo
trunk
, a un directorio de destino,
- Confirme los cambios para finalizar la acción de copia.
Deberá realizar esta acción de forma remota en el servidor, ya que realizar esa copia localmente es una operación de tiempo lineal, con archivos que se copian y enlazan. Esta es una operación muy lenta , mientras que hacerlo en el servidor es una operación de tiempo constante. Tenga en cuenta que incluso cuando se realiza la bifurcación en el servidor, la subversión requiere una confirmación cuando se bifurca mientras que git no, lo cual es una diferencia clave. Ese es un tipo de sobrecarga que hace que SVN sea marginalmente menos barato que Git.
El comando para cambiar ramas en SVN , es decir svn switch
, es realmente el svn update
disfraz. Gracias al concepto de directorio virtual, el comando es un poco más flexible en svn que en git. Los subdirectorios en su espacio de trabajo se pueden cambiar para reflejar otra url del repositorio. Lo más parecido sería usarlo, git-submodule
pero usarlo es semánticamente bastante diferente de la ramificación. Desafortunadamente, esta es también una decisión de diseño que hace que el cambio sea un poco más lento en SVN que en Git, ya que tiene que verificar cada directorio de espacio de trabajo en qué url remota está reflejando. En mi experiencia, Git es más rápido para cambiar de rama que SVN.
La ramificación de SVN tiene un costo ya que copia archivos y siempre debe estar disponible públicamente. En git, como se explicó anteriormente, las ramas son "solo referencias" y pueden mantenerse en su repositorio local y publicarse a su discreción. Sin embargo, en mi experiencia, SVN sigue siendo notablemente más barato y más eficiente que, por ejemplo, ClearCase.
Es un fastidio que SVN no esté descentralizado. Puede tener múltiples repositorios reflejados en algún repositorio de origen, pero no es posible sincronizar cambios diferentes en múltiples repositorios SVN, ya que SVN no tiene identificadores únicos para confirmaciones (git ha identificado identificadores basados en el contenido de la confirmación). Sin embargo, la razón por la que personalmente comencé a usar git sobre SVN es porque iniciar un repositorio es notablemente más fácil y más barato en git . Conceptualmente en términos de gestión de configuración de software, cada copia divergente de un proyecto (clon, fork, espacio de trabajo o lo que sea) es una "rama", y dada esta terminología, crear una nueva copia en SVN no es tan barato como Git, donde este último tiene ramas "incorporadas".
Como otro ejemplo, en Mercurial , la ramificación comenzó un poco diferente como un DVCS y la creación / destrucción de ramas con nombre requirió confirmaciones separadas. Los desarrolladores de Mercurial implementados más tarde en los marcadores de desarrollo para imitar el mismo modelo de ramificación de git, aunque heads
se llaman tips
y en su lugar branches
están bookmarks
en terminología mercurial.
This command causes a near-instantaneous commit in the repository, creating a new directory in revision 341. The new directory is a copy of /calc/trunk.
- Crear la rama es trivial en SVN, a menos que esté haciendo una copia explícita de cada archivo.El costo real de una sucursal es fusionarla. Git hace esto más fácil que algunos otros sistemas de control de fuente. Consulte la pregunta sobre desbordamiento de pila. ¿ Cómo y / o por qué es mejor combinar en Git que en SVN? .
fuente
En Git, una rama es solo una referencia a un compromiso con el repositorio local. Crearlo es muy barato, no hay red en absoluto. No del todo gratis (tienes que escribir un comando), pero muy cerca.
La ramificación no es particularmente costosa en SVN: es solo una copia, que es una confirmación muy barata. SVN tiene un modelo de repositorio central, por lo que es un acceso a la red, pero no uno horrible.
En el venerable CVS, por otro lado, la ramificación es MUY costosa. Básicamente, las ramas CVS implican agregar una etiqueta, pero en CVS eso significa que TODOS LOS ARCHIVOS AFECTADOS deben modificarse. Cada archivo se reescribe para incluir la nueva etiqueta. Eso es terriblemente caro. Y si su repositorio es grande, también es terriblemente lento. De hecho, si estás en un gran proyecto, es lo suficientemente lento como para que algunas personas eviten hacer ramas si pueden.
fuente
La ramificación de SVN es tan gratuita como la de Git. Es solo un poco de datos de limpieza que dice dónde comienza la sucursal, sin cambios en los archivos almacenados. Una 'copia' en SVN es como agregar un enlace simbólico a un directorio Unix. Tenga en cuenta que la rama SVN no requerirá un viaje de red hasta que confirme los cambios de su copia de trabajo (pero no tiene mucho sentido tener un SCM si no se compromete fuera de lugar en algún momento).
Tenga en cuenta que una rama de Git también implicará un poco de limpieza, como agregar esa etiqueta internamente, que tendrá que almacenarse en algún lugar cuando realice la confirmación. No es gran cosa, por eso se llama 'gratis'.
fuente
Es 'gratis' (en este contexto, 'gratis' realmente significa rápido y fácil y no ocupa espacio) porque en algunos sistemas de control de versiones anteriores una rama era una copia completa del código en ese punto, por lo que las ramas tomaron mucho espacio y fue fácil terminar con muchas versiones completamente completas del software, que luego tomaron la gestión. En otros, no era una copia completa del código, pero todos los archivos aún tenían que modificarse para una etiqueta, por lo que era lento y doloroso ('costoso').
Las ramas de git son esencialmente etiquetas que apuntan a una confirmación y, por lo tanto, evitan los problemas anteriores.
fuente
Otro aspecto de "gratis / barato / costoso" tiene que ver con el costo en términos de recursos del desarrollador para hacer frente a las consecuencias posteriores de la ramificación; es decir, el proceso de fusión de cambios de sucursales.
Y aquí, fusionar sucursales en sistemas DVCS como Git y Mercurial es más fácil que en sistemas más antiguos ... porque los sistemas DVCS hacen un trabajo mucho mejor al rastrear el historial de las versiones en el gráfico; es decir, donde se ha producido una fusión previa. Esto hace que las fusiones sean más precisas, reduce conflictos innecesarios y ... hace que la fusión subjetivamente sea "más fácil" o "menos aterradora" para los desarrolladores involucrados.
fuente