Pregunta ¿Por qué git fast-forward se fusiona de forma predeterminada?


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

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

Entonces, pensar en el futuro: soy el único que trabaja en este proyecto. Si utilizo el enfoque predeterminado de git (fusión de avance rápido), mi historial daría como resultado una rama principal gigante. Nadie sabe que utilicé una sucursal por separado para cada función, porque al final solo tendré esa rama maestra gigante. ¿No se verá eso 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 esto?


608
2018-05-17 15:26


origen


Respuestas:


La fusión rápida tiene sentido para las sucursales efímeras, pero de una manera más historia complejaLa fusión no rápida puede hacer que el historial sea más fácil de comprender y facilitar la reversión de un grupo de confirmaciones.

Advertencia: El reenvío rápido también tiene posibles efectos secundarios. Por favor revise https://sandofsky.com/blog/git-workflow.html, evite el "no-ff" con sus "compromisos de punto de control" que rompan la culpa o bisección, y considere cuidadosamente si debe ser su enfoque predeterminado para master.

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

Incorporando una característica terminada en desarrollar

Las funciones finalizadas se pueden fusionar en la rama de desarrollo 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

los --no-ff marca la fusión para crear siempre un nuevo objeto de confirmación, incluso si la combinación se puede realizar con un avance rápido. Esto evita perder información sobre la existencia histórica de una rama de características y agrupa todas las confirmaciones que juntas agregaron la característica.

Jakub Narębski además menciona el config merge.ff:

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


El avance rápido es el valor predeterminado porque:

  • las ramas efímeras son muy fáciles de crear y usar en Git
  • Las ramas efímeras a menudo aíslan muchos commits que se pueden reorganizar libremente dentro de esa rama
  • esos commits son en realidad parte de la rama principal: una vez reorganizada, la rama principal se reenvía rápidamente para incluirlos.

Pero si anticipa un flujo de trabajo iterativo en una rama tema / característica (es decir, me fusiono, luego vuelvo a esta rama de características y agrego 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 de características.

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 agrega en los comentarios:

Veo algo de sentido en el avance rápido para las ramas [efímeras], pero convertirla en la acción predeterminada significa que git lo asume ... a menudo tiene ramas [efímeras]. ¿Razonable?

Jefromi responde:

Creo que la vida útil de las sucursales varía mucho de un usuario a otro. Entre los usuarios experimentados, sin embargo, es probable que haya una tendencia a tener ramas mucho más efímeras.

A mi, una rama de vida corta es una que creo para hacer una cierta operación más fácil (parcheo y prueba de rebase, probable o rápido), y luego elimine inmediatamente una vez que haya terminado.
  Eso significa que es probable debe ser absorbido por la rama temática de la cual se bifurcóy la rama de tema se fusionará como una sola rama. Nadie necesita saber lo que hice internamente para crear la serie de compromisos que implementan esa característica.

De manera más general, agrego:

realmente depende de tu 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 varias veces, varias ramas tienen sentido.

Ver "¿Cuándo deberías ramificarte?"

En realidad, cuando se considera el modelo de la rama Mercurial, está en su núcleo uno rama por repositorio (aunque puedes crear cabezas anónimas, marcadores e incluso ramas nombradas)
Ver "Git y Mercurial: comparar y contrastar".

Mercurial, de forma predeterminada, utiliza líneas de código ligeras anónimas, que en su terminología se denominan "cabezas".
  Git usa ramas ligeras con nombre, con mapeo inyectivo para mapear los nombres de las ramas en el repositorio remoto a los nombres de las ramas de seguimiento remoto.
  Git lo "obliga" a nombrar las 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 de ramas múltiples, como flujo de trabajo de rama de tema, lo que significa ramas múltiples en un paradigma de repositorio único.


685
2018-05-17 15:31



Déjame expandir un poco en una VonCes respuesta muy completa:


En primer lugar, si recuerdo correctamente, el hecho de que Git por defecto no crea merge commits en el avance rápido caso ha venido de considerar "repositorios iguales" de una rama, donde el tirón mutuo se usa para sincronizar esos dos repositorios (un flujo de trabajo que puede encontrar como primer ejemplo en la mayoría de la documentación del usuario, incluido "El Manual del usuario de Git" y "Control de versiones por ejemplo"). En este caso, no usa la función de extracción para fusionar la rama completamente realizada, la usa para mantenerse al día con otros trabajos. No querrás tener un hecho efímero y sin importancia cuando guardes 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 más tarde, con un uso más generalizado de VCS con un buen soporte de fusión, y con la prueba de diversos flujos de trabajo basados ​​en fusiones. Es por eso que, por ejemplo, Mercurial originalmente solo admitía una sucursal por depósito (más consejos anónimos para rastrear sucursales remotas), como se vio en revisiones anteriores de "Mercurial: The Definitive Guide".


Segundo, cuando sigues mejores prácticas de uso ramas de características, es decir, que las ramas de características deberían comenzar desde una versión estable (por lo general, desde la última versión), para poder elegir y seleccionar qué características incluir seleccionando qué característica se ramifica para fusionar, Usualmente no estás en una situación de rápido avance... lo que hace que este tema sea discutible. Debe preocuparse por crear una combinación real y no avanzar cuando se fusiona una primera rama (suponiendo que no se realicen cambios de compromiso único directamente en 'master'); todas las otras fusiones posteriores son, por supuesto, en una situación no rápida.

HTH


40
2018-05-31 13:30