¿Por qué Git se fusiona de forma rápida por defecto?


Viniendo de mercurial, uso ramas para organizar características. Naturalmente, también quiero ver este flujo de trabajo en mi historia.

Comencé mi nuevo proyecto usando git y terminé mi primera característica. Al fusionar la característica, me di cuenta de que git usa avance rápido, es decir, aplica mis cambios directamente a la rama maestra si es posible y se olvida de mi rama.

Así que para pensar en el futuro: soy el único que trabaja en este proyecto. Si utilizo el enfoque predeterminado de git (avance rápido fusión), mi historia resultaría en una rama maestra gigante. Nadie sabe que usé una rama separada para cada característica, porque al final solo tendré esa rama maestra gigante. ¿No te parecerá poco profesional?

Con este razonamiento, no quiero una fusión rápida y no puedo ver por qué es la predeterminada. ¿Qué tiene de bueno?

Author: Nick Volynkin, 2010-05-17

2 answers

La fusión de avance rápido tiene sentido para ramas de corta duración, pero en un historial más complejo , la fusión no de avance rápido puede hacer que el historial sea más fácil de entender, y que sea más fácil revertir un grupo de commits.

Advertencia: La falta de avance rápido también tiene efectos secundarios potenciales. Por favor revise https://sandofsky.com/blog/git-workflow.html , evite el 'no-ff' con sus "commits de punto de control" que rompen el bisect o la culpa, y considere cuidadosamente si debe ser su enfoque predeterminado para master.

texto alt
(De nvie.com, Vincent Driessen , post "Un exitoso modelo de ramificación de Git")

Incorporar una característica terminada en develop

Las características terminadas se pueden fusionar en la rama develop para agregarlas a la próxima versión:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

La bandera --no-ff hace que la combinación siempre cree un nuevo commit object, incluso si la fusión se puede realizar con un avance rápido. Esto evita perder información sobre la existencia histórica de una rama de característica y agrupa todas las confirmaciones que agregaron la característica.

Jakub Narębski también menciona el config merge.ff:

De forma predeterminada, Git no crea un commit de fusión adicional cuando se fusiona un commit que es un descendiente del commit actual. En cambio, la punta de la la rama actual se reenvía rápidamente.
Cuando se establece en false, esta variable le dice a Git que cree una confirmación de fusión adicional en tal caso (equivalente a dar la opción --no-ff desde la línea de comandos).
Cuando se establece en ' only', solo se permiten tales fusiones de avance rápido (equivalente a dar la opción --ff-only desde la línea de comandos).


El avance rápido es el predeterminado porque:

  • las ramas de corta duración son muy fáciles de crear y usar en Git
  • las ramas de corta duración a menudo aíslan muchas confirmaciones que se pueden reorganizar libremente dentro de esa rama{[68]]}
  • esas confirmaciones son en realidad parte de la rama principal: una vez reorganizadas, la rama principal se reenvía rápidamente para incluirlas.

Pero si anticipa un flujo de trabajo iterativo en una rama topic/feature (es decir, me fusiono, luego vuelvo a esta rama feature y añado algunas confirmaciones más), entonces es útil incluir solo la fusión en la rama principal, en lugar de todas las confirmaciones intermedias de la rama feature.

En este caso, puede terminar configurando este tipo de archivo de configuración :

[branch "master"]
# This is the list of cmdline options that should be added to git-merge 
# when I merge commits into the master branch.

# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.

# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.

mergeoptions = --no-commit --no-ff

El OP añade en los comentarios:

Veo cierto sentido en el avance rápido para las ramas [de corta duración], pero convertirla en la acción predeterminada significa que git asume que usted... a menudo tienen ramas [de corta duración]. Razonable?

Jefromi responde:

Creo que la vida útil de las ramas varía mucho según el usuario al usuario. Sin embargo, entre los usuarios experimentados, probablemente haya una tendencia a tener ramas mucho más efímeras.

Para mí, una rama de corta duración es una que creo con el fin de hacer una cierta operación más fácil (rebasing, probable, o parches y pruebas rápidas), y luego eliminar inmediatamente una vez que haya terminado.
Eso significa que es probable que se absorba en la rama topic de la que se bifurcó, y la rama topic se fusionará como una rama. Nadie necesita saber lo que hice internamente para crear la serie de commits implementando esa característica dada.

Más generalmente, añado: {[12]]}

Realmente depende de su flujo de trabajo de desarrollo:

  • si es lineal, una rama tiene sentido.
  • Si necesita aislar características y trabajar en ellas durante un largo período de tiempo y fusionarlas repetidamente, varias ramas tienen sentido.

Véase "¿Cuándo debería ¿branch?"

En realidad, cuando se considera el modelo de rama Mercurial, está en su núcleo una rama por repositorio (aunque puede crear cabezas anónimas, marcadores e incluso ramas con nombre)
Ver "Git and Mercurial - Compare and Contrast".

Mercurial, por defecto, utiliza líneas de código ligeras anónimas, que en su terminología se llaman "cabezas".
Git utiliza ramas con nombre ligeras, con asignación inyectiva para asignar nombres de ramas en repositorio remoto a nombres de ramas de seguimiento remoto.
Git " te obliga "a nombrar ramas (bueno, con la excepción de una sola rama sin nombre, que es una situación llamada" CABEZA separada"), pero creo que esto funciona mejor con flujos de trabajo con ramas pesadas, como el flujo de trabajo de ramas temáticas, lo que significa múltiples ramas en un único paradigma de repositorio.

 688
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:34

Permítanme ampliar un poco sobre una VonC ' s respuesta muy completa :


En primer lugar, si lo recuerdo correctamente, el hecho de que Git por defecto no crea merge commits en el caso fast-forward proviene de considerar "repositorios iguales" de rama única, donde mutual pull se usa para sincronizar esos dos repositorios (un flujo de trabajo que puede encontrar como primer ejemplo en la documentación de la mayoría de los usuarios, incluido "El Manual del usuario de Git" y " Control de versiones por Ejemplo"). En este caso no se utiliza pull para fusionar rama completamente realizada, se utiliza para mantenerse al día con otros trabajos. No querrás tener un hecho efímero y sin importancia cuando hagas una sincronización guardada y almacenada en el repositorio, guardada para el futuro.

Tenga en cuenta que la utilidad de las ramas de características y de tener múltiples ramas en un solo repositorio vino solo más tarde, con un uso más generalizado de VCS con un buen soporte de fusión, y con probar varios flujos de trabajo basados en fusión. Es por eso que por ejemplo, Mercurial originalmente soportaba solo una rama por repositorio (más consejos anónimos para rastrear ramas remotas), como se ve en revisiones anteriores de "Mercurial: The Definitive Guide".


En segundo lugar, al seguir las mejores prácticas de usar ramas de características, es decir, que las ramas de características deben comenzar desde la versión estable (generalmente desde la última versión), para poder seleccionar y seleccionar qué características incluir seleccionando qué ramas de características merge, normalmente no estás en una situación de avance rápido... lo que hace que este tema sea discutible. Debe preocuparse por crear una verdadera fusión y no un avance rápido al fusionar una primera rama (suponiendo que no coloque cambios de confirmación única directamente en 'master'); todas las demás fusiones posteriores están, por supuesto, en una situación no de avance rápido.

HTH

 40
Author: Jakub Narębski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-25 16:19:00