¿Por qué squash git se compromete para solicitudes de extracción?

159

¿Por qué todos los repositorios serios de Github que hago solicitan que me aplasten mis compromisos en un solo compromiso?

Pensé que el registro de git estaba allí para que pudieras inspeccionar todo tu historial y ver exactamente qué cambios ocurrieron en ese lugar, pero al eliminarlo del historial se eliminan todos y se agrupan en un solo compromiso. ¿Cuál es el punto?

Esto también parece ir en contra del mantra "cometer temprano y cometer a menudo".

    
pregunta hamstar 18.11.2014 - 23:41
fuente

5 respuestas

140

Para que tenga un historial de git claro y conciso que documente de forma clara y sencilla los cambios realizados y las razones por las que.

Por ejemplo, un registro de git típico "no colocado" podría parecerse a lo siguiente:

7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
787g8fgf78... hotfix for #5849564648
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

¡Qué desastre!

Mientras que un registro de git más cuidadosamente administrado y fusionado con un poco de enfoque adicional en los mensajes para esto podría parecerse a:

7hgf8978g9... 8483948393 Added new slideshow feature
787g8fgf78... 5849564648 Hotfix for android display issue
9080gf6567... 6589685988 Implemented pop-up to select language

Creo que se puede ver el punto de aplastar las confirmaciones y el mismo principio se aplica a las solicitudes de extracción: Legibilidad del historial. También puede agregar a un registro de confirmación que ya tiene cientos o incluso Miles de confirmaciones y esto ayudará a que la historia en crecimiento sea breve y concisa.

Quiere comprometerse temprano y con frecuencia. Es una buena práctica por muchas razones. Me parece que esto me lleva a tener confirmaciones frecuentes que son "wip" (work-in-progress) o "part A done" o "typo, minor fix" donde estoy usando git para ayudarme a trabajar y darme puntos de trabajo que Puedo regresar si el siguiente código no funciona a medida que avanzo para que las cosas funcionen. Sin embargo, no necesito ni quiero ese historial como parte del historial final de git, por lo que puedo aplastar mis compromisos, pero vea las notas a continuación sobre lo que esto significa en una rama de desarrollo frente a un maestro.

Si hay hitos importantes que representan distintas etapas de trabajo, todavía está bien tener más de un compromiso por función / tarea / error. Sin embargo, esto a menudo puede resaltar el hecho de que el ticket en desarrollo es "demasiado grande" y debe dividirse en partes más pequeñas que puedan ser independientes, por ejemplo:

8754390gf87... Implement feature switches

parece "1 pieza de trabajo". ¡O existen o no existen! No parece tener sentido romperlo. Sin embargo, la experiencia me ha demostrado que, dependiendo del tamaño y la complejidad de la organización, una ruta más detallada podría ser:

fgfd7897899... Add field to database, add indexes and a trigger for the dw group
9458947548g... Add 'backend' code in controller for when id is passed in url.
6256ac24426... Add 'backend' code to make field available for views.
402c476edf6... Add feature to UI

Las piezas pequeñas significan revisiones de código más fáciles, pruebas de unidad más fáciles, mejor oportunidad de qa, mejor alineación con el Principio de Responsabilidad Única, etc.

Para los aspectos prácticos de cuándo realizar realmente tales aplastamientos, hay básicamente dos etapas distintas que tienen su propio flujo de trabajo

  • tu desarrollo, por ejemplo atraer solicitudes
  • su trabajo agregado a la rama de la línea principal, por ejemplo, maestro

Durante su desarrollo, confirma mensajes "temprano y frecuente" y con mensajes rápidos "desechables". Es posible que desee aplastar aquí algunas veces, por ejemplo. Squashing en wip y todo el mensaje se compromete. Está bien, dentro de la rama, retener múltiples confirmaciones que representan pasos distintos que realizó en el desarrollo. La mayoría de los squashes que elijas hacer deben estar dentro de estas ramas de características, mientras se desarrollan y antes de fusionarse para dominar. Al agregar a la rama de la línea principal desea que las confirmaciones sean concisas y estén correctamente formateadas de acuerdo con el historial de la línea principal existente. Esto podría incluir el ID del sistema del rastreador de tickets, por ejemplo, JIRA como se muestra en los ejemplos. El squash no se aplica realmente aquí a menos que desee 'enrollar' varias confirmaciones distintas en el master. Normalmente no lo haces.

El uso de --no-ff al fusionarse con el maestro utilizará un compromiso para la combinación y también conservará el historial (en la rama). Algunas organizaciones consideran que esto es una buena práctica. Vea más en enlace También verá el efecto práctico en git log , donde un --no-ff commit será el último commit , en la parte superior de la CABEZA (cuando se acaba de hacer), mientras que sin --no-ff puede estar más abajo en la historia, dependiendo de las fechas y otros compromisos.

    
respondido por el Michael Durrant 19.11.2014 - 01:26
fuente
21

Debido a que a menudo a la persona que está haciendo un PR le preocupa el efecto neto de las "características agregadas X" de las confirmaciones, no sobre las "plantillas base, la función de corrección de errores X, la función de agregar Y, los errores tipográficos corregidos en los comentarios, los parámetros de escala de datos ajustados, el hashmap se desempeña mejor que la lista "... nivel de detalle

Si piensa que sus 16 confirmaciones están mejor representadas por 2 confirmaciones en lugar de 1 "Característica X agregada, factorizado Z para usar X", entonces es probable que se proponga un pr con 2 confirmaciones, pero entonces podría ser es mejor proponer 2 pras separadas en ese caso (si el repositorio todavía insiste en comillas de comillas únicas)

Esto no va en contra del mantra de "cometer temprano y cometer con frecuencia", como en su repo, mientras se está desarrollando, todavía tiene los detalles granulares, por lo que tiene una mínima posibilidad de perder el trabajo, y otras personas pueden revisar / Tire / proponga programas en contra de su trabajo mientras se desarrolla el nuevo programa.

    
respondido por el Andrew Hill 19.11.2014 - 00:25
fuente
13

La razón principal de lo que puedo ver es la siguiente:

  • La interfaz de usuario de GitHub para fusionar solicitudes de extracción actualmente (octubre de 2015) no le permite editar la primera línea del mensaje de confirmación, lo que obliga a que sea Merge pull request #123 from joebloggs/fix-snafoo
  • La interfaz de usuario de GitHub para explorar el historial de confirmaciones actualmente no le permite ver el historial de la rama desde el punto de vista --first-parent
  • La interfaz de usuario de GitHub para ver la culpa de un archivo actualmente no le permite ver la culpa del archivo con el punto de vista --first-parent (tenga en cuenta que esto solo se solucionó en Git 2.6.2, por lo que podríamos perdona a GitHub por no tenerlo disponible)

Entonces, cuando combinas las tres situaciones anteriores, obtienes una situación en la que las confusiones no ocultadas que se fusionan lucen feas desde la interfaz de usuario de GitHub.

Tu historial con confirmaciones aplastadas se verá algo así como

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature
56556316ad... Merge pull request #324 from ahacker/fix-android-display
787g8fgf78... Hotfix for android display issue
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... Implemented pop-up to select language

Mientras que sin comillas aplastadas, el historial se verá algo así como

1256556316... Merge pull request #423 from jrandom/add-slideshows
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... Merge pull request #324 from ahacker/fix-android-display
787g8fgf78... hotfix for #5849564648
f56556316e... Merge pull request #28 from somwhere/select-lang-popup
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Cuando tienes muchas confirmaciones en un seguimiento de relaciones públicas en las que se produjo un cambio puede convertirse en una pesadilla si te limitas a usar la interfaz de usuario de GitHub .

Por ejemplo, encuentra un puntero nulo que no está referenciado en algún lugar de un archivo ... por lo que dice "¿quién hizo esto y cuándo? ¿Qué versiones de versiones están afectadas?". Luego pasas a la vista de culpa en la interfaz de usuario de GitHub y ves que la línea se cambió en 789fdfffdf ... "Oh, pero espera un segundo, esa línea solo tuvo su sangría cambiada para encajar con el resto del código ", por lo que ahora necesita navegar hasta el estado del árbol para ese archivo en la confirmación principal y volver a visitar la página de la culpa ... eventualmente encontrará la confirmación ... es una confirmación de hace 6 meses ..." oh **** Esto podría estar afectando a los usuarios durante 6 meses "dices ... ah, pero espera, ese compromiso estaba en realidad en una solicitud de extracción y solo se fusionó ayer y nadie ha cortado aún un lanzamiento ..." Maldita sea, gente por fusionar confirmaciones sin aplastar la historia "es el grito que generalmente se puede escuchar después de aproximadamente 2 o 3 expediciones de arqueología de códigos a través de la interfaz de usuario de GitHub

Ahora veamos cómo funciona esto si usas la línea de comandos Git (y 2.6.2 que tiene la solución para git blame --first-parent )

  • Si estuviera usando la línea de comandos de Git, podría controlar completamente el mensaje de confirmación de combinación y, por lo tanto, la confirmación de combinación podría tener una buena línea de resumen.

Por lo que nuestro historial de compromisos se vería como

$ git log
1256556316... #423 Added new slideshow feature
7hgf8978g9... Added new slideshow feature, JIRA # 848394839
85493g2458... Fixed slideshow display issue in ie
gh354354gh... wip, done for the week
789fdfffdf... minor alignment issue
56556316ad... #324 Hotfix for android display issue
787g8fgf78... hotfix for #5849564648
f56556316e... #28 Implemented pop-up to select language
9080gf6567... implemented feature # 65896859
gh34839843... minor fix (typo) for 3rd test

Pero también podemos hacer

$ git log --first-parent
1256556316... #423 Added new slideshow feature
56556316ad... #324 Hotfix for android display issue
f56556316e... #28 Implemented pop-up to select language

(En otras palabras: el CLI de Git te permite tener tu pastel y comerlo también)

Ahora, cuando alcanzamos el problema del puntero nulo ... bueno, solo usamos git blame --first-parent -w dodgy-file.c y de inmediato se nos da la confirmación exacta donde se introdujo la de-referencia del puntero nulo en la rama maestra, ignorando los simples cambios de espacios en blanco. >

Por supuesto, si está realizando combinaciones usando la interfaz de usuario de GitHub, git log --first-parent es realmente horrible gracias a que GitHub forzó la primera línea del mensaje de confirmación de fusión:

1256556316... Merge pull request #423 from jrandom/add-slideshows
56556316ad... Merge pull request #324 from ahacker/fix-android-display
f56556316e... Merge pull request #28 from somwhere/select-lang-popup

Así que para acortar una larga historia corta:

La interfaz de usuario de GitHub (octubre de 2015) tiene una serie de inconvenientes con la forma en que combina las solicitudes de extracción, la forma en que presenta el historial de confirmación y la forma en que atribuye la información de la culpa. La mejor forma actual de solucionar estos defectos en la interfaz de usuario de GitHub es solicitar a las personas que aplasten sus compromisos antes de fusionarse.

El CLI de Git no tiene estos problemas y puede elegir fácilmente qué vista desea ver para que ambos puedan descubrir la razón por la que un cambio en particular se realizó de esa manera (al mirar el historial de los comillas no escritas) así como ver los compromisos efectivamente aplastados.

Publicar guión

La razón final a menudo citada para los intentos de aplastamiento es hacer que el backporting sea más fácil ... si solo tiene un compromiso para el puerto de retroceso (es decir, el compromiso aplastado), entonces es fácil elegirlo ...

Bueno, si estás viendo el historial de git con git log --first-parent , entonces puedes seleccionar las confirmaciones de fusión. La mayoría de la gente se confunde con las combinaciones de selección de cherry porque tiene que especificar la opción -m N pero si recibió la confirmación de git log --first-parent , entonces sabe que es el primer padre que desea seguir, así que será git cherry-pick -m 1 ...

    
respondido por el Stephen Connolly 20.10.2015 - 11:18
fuente
1

Estoy de acuerdo con los sentimientos expresados en otras respuestas en este hilo acerca de mostrar un historial claro y conciso de las características agregadas y los errores solucionados. Sin embargo, quería abordar otro aspecto que su pregunta eludió pero no mencionó explícitamente. Parte del problema que puede tener acerca de algunos de los métodos de trabajo de git es que git le permite reescribir la historia, lo que parece extraño cuando se le presenta git después de usar otras formas de control de código fuente donde tales acciones son imposibles. Además, esto también va en contra del principio generalmente aceptado del control de fuente de que una vez que algo se confirma / se registra en el control de fuente, debería poder revertir a ese estado sin importar qué cambios realice después de esa confirmación. Como implica en su pregunta, esta es una de esas situaciones. Creo que git es un gran sistema de control de versiones; sin embargo, para comprenderlo, debe comprender algunos de los detalles de implementación y las decisiones de diseño que se encuentran detrás, y como resultado tiene una curva de aprendizaje más pronunciada. Tenga en cuenta que git estaba destinado a ser un sistema de control de versiones distribuido y eso ayudará a explicar por qué los diseñadores permiten que el historial de git se vuelva a escribir con las confirmaciones de squash como ejemplo.

    
respondido por el Fred Thomsen 22.11.2014 - 21:21
fuente
0

Debido a la perspectiva ... La mejor práctica es tener un solo compromiso por cada problema único <<issue-management-system>> si es posible.

Puede tener tantas confirmaciones como desee en su propia función / rama, pero su historial es relevante para lo que está haciendo ahora para SU perspectiva ... no es la HISTORIA de todo el EQUIPO / PROYECTO o La aplicación desde su perspectiva se mantendrá dentro de varios meses ...

Entonces, cuando quiera cometer una corrección de errores o una función en un repositorio común (este ejemplo es con la rama de desarrollo), puede hacerlo de la siguiente manera:

cómo hacer un repaso de la rama de tu característica para que se desarrolle rápidamente

    # set your current branch , make a backup of it , caveat minute precision
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # squash all your changes at once 
    git reset $(git merge-base develop $curr_branch)

    # check the modified files to add 
    git status

    # add the modified files dir by dir, or file by file or all as shown
    git add --all 

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # add the single message of your commit for the stuff you did 
    git commit -m "<<MY-ISSUE-ID>>: add my very important feature"

    # check once again 
    git log --format='%h %ai %an %m%m %s'  | less

    # make a backup once again , use seconds precision if you were too fast ... 
    curr_branch=$(git rev-parse --abbrev-ref HEAD); git branch "$curr_branch"--$(date "+%Y%m%d_%H%M"); git branch -a | grep $curr_branch | sort -nr

    # compare the old backup with the new backup , should not have any differences 
    git diff <<old-backup>>..<<new-backup-branch>>


    # you would have to git push force to your feature branch 
    git push --force 
    
respondido por el Yordan Georgiev 10.04.2018 - 11:14
fuente

Lea otras preguntas en las etiquetas