¿Cuál es la diferencia entre `git merge` y` git merge –no-ff`?

Usando el gitk log , no pude detectar una diferencia entre los dos. ¿Cómo puedo observar la diferencia (con un command git o alguna herramienta)?

El indicador --no-ff evita que la git merge ejecute un "avance rápido" si detecta que su HEAD actual es un ancestro de la confirmación que está intentando fusionar. Un avance rápido es cuando, en lugar de build un commit de fusión, git simplemente mueve su puntero de sucursal para apuntar a la confirmación entrante. Esto ocurre comúnmente cuando se hace un git pull sin ningún cambio local.

Sin embargo, en ocasiones desea evitar que ocurra este comportamiento, generalmente porque desea mantener una topología de bifurcación específica (por ejemplo, se está fusionando en una twig de tema y desea asegurarse de que se vea de esa manera cuando se lee el historial). Para hacer eso, puede pasar el indicador --no-ff y la git merge siempre buildá una combinación en lugar de un reenvío rápido.

De manera similar, si desea ejecutar un git pull o usar git merge para avanzar de forma explícita y desea realizar el rescate si no puede avanzar rápidamente, puede usar el --ff-only . De esta forma, puede hacer regularmente algo como " git pull --ff-only sin pensar, y luego, si se equivoca, puede regresar y decidir si desea fusionar o volver a establecer la base.

Respuesta gráfica a esta pregunta

Aquí hay un sitio con una explicación clara e ilustración gráfica del uso de git merge --no-ff :

diferencia entre git merge --no-ff y git merge

Hasta que vi esto, estaba completamente perdido con git. El uso de --no-ff permite que alguien revise el historial para ver claramente en qué twig trabajaste. (ese enlace apunta a la herramienta de visualización de "networking" de github) Y aquí hay otra gran reference con ilustraciones. Esta reference complementa muy bien la primera con más énfasis en aquellos less familiarizados con git.


Información básica para los recién nacidos como yo

Si eres como yo, y no un Git-guru, mi respuesta aquí describe cómo manejar la eliminación de files del seguimiento de git sin eliminarlos del sistema de files local, que parece estar mal documentado pero a menudo ocurre. Otra situación nueva es get el código actual , que todavía se las arregla para eludirme.


Ejemplo de flujo de trabajo

Actualicé un package a mi website y tuve que volver a mis notas para ver mi flujo de trabajo; Pensé que era útil agregar un ejemplo a esta respuesta.

Mi flujo de trabajo de los commands de git:

 git checkout -b contact-form (do your work on "contact-form") git status git commit -am "updated form in contact module" git checkout master git merge --no-ff contact-form git branch -d contact-form git push origin master 

Abajo: uso real, incluidas las explicaciones.
Nota: el resultado a continuación se corta; git es bastante detallado.

 $ git status # On branch master # Changed but not updated: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: ecc/Desktop.php # modified: ecc/Mobile.php # deleted: ecc/ecc-config.php # modified: ecc/readme.txt # modified: ecc/test.php # deleted: passthru-adapter.igs # deleted: shop/mickey/index.php # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # ecc/upgrade.php # ecc/webgility-config.php # ecc/webgility-config.php.bak # ecc/webgility-magento.php 

Note 3 cosas de arriba:
1) En la salida, puede ver los cambios de la actualización del package ECC, incluida la adición de nuevos files.
2) También note que hay dos files (no en la carpeta /ecc ) que borré independientemente de este cambio. En lugar de confundir esas eliminaciones de files con ecc , haré una twig de cleanup diferente más tarde para reflejar la eliminación de esos files.
3) ¡No seguí mi flujo de trabajo! Me olvidé de git mientras intentaba hacer que ecc volviera a funcionar.

Abajo: en lugar de hacer el git commit -am "updated ecc package" todo incluido git commit -am "updated ecc package" , normalmente lo haría, solo quería agregar los files en la carpeta /ecc . Esos files eliminados no formaban parte de mi git add , pero como ya se habían rastreado en git, debo eliminarlos de la confirmación de esta twig:

 $ git checkout -b ecc $ git add ecc/* $ git reset HEAD passthru-adapter.igs $ git reset HEAD shop/mickey/index.php Unstaged changes after reset: M passthru-adapter.igs M shop/mickey/index.php $ git commit -m "Webgility ecc desktop connector files; integrates with Quickbooks" $ git checkout master D passthru-adapter.igs D shop/mickey/index.php Switched to branch 'master' $ git merge --no-ff ecc $ git branch -d ecc Deleted branch ecc (was 98269a2). $ git push origin master Counting objects: 22, done. Delta compression using up to 4 threads. Compressing objects: 100% (14/14), done. Writing objects: 100% (14/14), 59.00 KiB, done. Total 14 (delta 10), reused 0 (delta 0) To git@github.com:me/mywebsite.git 8a0d9ec..333eff5 master -> master 


Script para automatizar lo anterior

Habiendo utilizado este process más de 10 veces en un día, me he dedicado a escribir scripts por lotes para ejecutar los commands, así que hice un git_update.sh <branch> <"commit message"> casi correcto para realizar los pasos anteriores. Aquí está la fuente de Gist para esa secuencia de commands.

En lugar de git commit -am , estoy seleccionando files de la list "modificada" producidos a través git status y luego pegando esos en este script. Esto ocurrió porque realicé docenas de ediciones pero quería nombres de twigs variados para ayudar a agrupar los cambios.

La --no-ff asegura que no se realizará una fusión de reenvío rápido, y que siempre se creará un nuevo object de confirmación . Esto puede ser deseable si desea que git mantenga un historial de twigs de características. git merge --no-ff vs git merge En la image de arriba, el lado izquierdo es un ejemplo del historial de git después de usar git merge --no-ff y el lado derecho es un ejemplo de usar git merge donde fue posible una fusión ff.

EDITAR : una versión anterior de esta image indicaba solo un padre único para la confirmación de fusión. Las asignaciones de mezcla tienen varias confirmaciones principales que git usa para mantener un historial de la "twig de característica" y de la twig original. Los enlaces principales múltiples se resaltan en verde.

Esta es una vieja pregunta, y esto se menciona sutilmente en las otras publicaciones, pero la explicación que hizo que este clic para mí sea que las fusiones de avance no rápido requerirán una confirmación por separado .