2009-03-05 11 views
144

Tengo ocho commits en una rama que me gustaría enviar por correo electrónico a algunas personas que aún no están iluminadas. Hasta ahora, todo lo que hago me da 8 archivos de parche, o comienza a darme los archivos de parche para cada confirmación en el historial de la sucursal, desde el principio de los tiempos. Utilicé git rebase --interactive para aplastar los commits, pero ahora todo lo que intento me da millones de parches desde el principio de los tiempos. ¿Qué estoy haciendo mal?¿Cómo comprime squash en un parche con formato de parche git?

git format-patch master HEAD # yields zillions of patches, even though there's 
          # only one commit since master 
+0

Tengo curiosidad sobre qué método terminará usando entre las siguientes proposiciones. Háganos saber;) – VonC

+3

Voy a utilizar git diff como lo sugiere Rob Di Marco. Pero estoy fuera del trabajo por dos semanas, después de haber sido testigo del nacimiento de mi segunda bebé anoche, ¡así que pasará un tiempo antes de que lo use! :) – skiphoppy

+2

Me gustaría ver git format-patch --squash master HEAD – schoetbi

Respuesta

168

Recomendaría hacer esto en una rama de usar y tirar de la siguiente manera. Si sus cometa, está en el "saltos de línea" sucursal y que han cambiado de nuevo a su rama "master" ya, esto debería hacer el truco:

[[email protected] example (master)]$ git checkout -b tmpsquash 
Switched to a new branch "tmpsquash" 

[[email protected] example (tmpsquash)]$ git merge --squash newlines 
Updating 4d2de39..b6768b2 
Fast forward 
Squash commit -- not updating HEAD 
test.txt | 2 ++ 
1 files changed, 2 insertions(+), 0 deletions(-) 

[[email protected] example (tmpsquash)]$ git commit -a -m "My squashed commits" 
[tmpsquash]: created 75b0a89: "My squashed commits" 
1 files changed, 2 insertions(+), 0 deletions(-) 

[[email protected] example (tmpsquash)]$ git format-patch master 
0001-My-squashed-commits.patch 

Espero que esto ayude!

+2

Esto es lo que uso cuando quiero mantener el historial localmente (en caso de que necesite editar el parche). De lo contrario, solo uso rebase -i y aplazo los commits. – sebnow

+1

¡la mejor solución! gracias :) – kkudi

+5

para mí, funcionó más confiable con 'git comit -m" Mis commits aplastados "' de lo contrario agregaría otros archivos sin seguimiento – Sebastian

18

Como ya saben, un git format-patch -8 HEAD le dará ocho parches.

Si desea que sus 8 compromete aparecen como una sola, y no le importa volver a escribir la historia de su rama (o-o-X-A-B-C-D-E-F-G-H), usted podría:

git rebase -i 
// squash A, B, C, D, E ,F, G into H 

o, y sería una mejor solución, repetición todas sus confirmaciones de 8 X (la confirmación antes de que sus confirmaciones 8) en una nueva rama

git branch delivery X 
git checkout delivery 
git merge --squash master 
git format-patch HEAD 

de esta forma, sólo tienen un cometen en la rama "entrega", y que representan toda su pasado 8 de c ommits

+0

'git merge master' simplemente hace un avance rápido y no comprime commits en uno. Cambie a 'git merge --squash master' para obtener todos los commits aplastados y visibles en el área escenificada. Tu flujo funcionará con este cambio. (Estoy usando git versión 2.1.0.) – Stunner

+0

@Stunner buen punto. He editado la respuesta. – VonC

21

siempre uso git diff por lo que en tu ejemplo, algo así como

git diff master > patch.txt 
+14

Excepto que pierde todos los mensajes y metadatos de confirmación. La belleza del parche de formato git es que es posible reconstruir una rama completa a partir de un conjunto de parches. – mcepl

+0

el método create-branch-and-squash tiene la ventaja de combinar todos los mensajes de confirmación en uno, pero este método es mucho más rápido si desea escribir su propio mensaje de confirmación – woojoo666

+0

en realidad, se puede hacer un mensaje combinado usando 'git log ', ver [mi respuesta] (http://stackoverflow.com/a/32373193/1852456) para un ejemplo – woojoo666

120

sólo para añadir una solución más a la olla: Si utiliza este lugar:

git format-patch master --stdout > my_new_patch.diff 

entonces será todavía quedan 8 parches ... pero todos estarán en un solo archivo de parche y se aplicarán como uno con:

git am < my_new_patch.diff 
+13

Me gusta esta solución. Vale la pena notar que puede crear parches a veces mucho más grandes que el método descrito por @Adam Alexander. Esto se debe a que algunos archivos se pueden editar más de una vez a través de confirmaciones. Este método trata cada confirmación por separado, incluso si algún archivo se revirtió. Pero la mayoría de las veces esto no es un problema. – gumik

+1

¡Esta opción es excelente si intenta evitar la fusión! (por ejemplo, quieres omitir algunas confirmaciones). Todavía puedes 'git rebase -i ...' y aplastarlos todos a uno. –

17

Esta es una adaptación de la respuesta de Adam Alexander, en caso de que sus cambios estén en la rama principal. Esta haga lo siguiente:.

  • crea una nueva rama de usar y tirar "tmpsquash" desde el punto queremos (busque la clave SHA corriendo "git --log" o con gitg Seleccione el cometer quieres ser cabeza tmpsquash , los commits que están después de eso en master serán los commits aplastados).
  • Combina los cambios de maestro a tmpsquash.
  • Confirma los cambios aplastados en tmpsquash.
  • Crea el parche con los commit aplastados.
  • se remonta a la rama principal

[email protected]:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38 
[email protected]:~/example (master)$ git checkout tmpsquash 
Switched to branch 'tmpsquash' 
[email protected]:~/example (tmpsquash)$ git merge --squash master 
Updating ba3c498..40386b8 
Fast-forward 
Squash commit -- not updating HEAD 

[snip, changed files] 

11 files changed, 212 insertions(+), 59 deletions(-) 
[email protected]:~/example (tmpsquash)$ git commit -a -m "My squashed commits" 
[test2 6127e5c] My squashed commits 
11 files changed, 212 insertions(+), 59 deletions(-) 
[email protected]:~/example (tmpsquash)$ git format-patch master 
0001-My-squashed-commits.patch 
[email protected]:~/example (tmpsquash)$ git checkout master 
Switched to branch 'master' 
[email protected]:~/example (master)$ 
+0

Hacer cambios en el maestro es un antipatrón si no los empujará al control remoto. Y si lo hace, probablemente no necesite generar archivos de parches para ellos. –

0

Sobre la base de la respuesta de Adam Alexander:

git checkout newlines 
## must be rebased to master 
git checkout -b temporary 
# squash the commits 
git rebase -i master 
git format-patch master 
4

Formato parche entre dos etiquetas:

git checkout <source-tag> 
git checkout -b <tmpsquash> 
git merge --squash <target-tag> 
git commit -a -m "<message>" 
git format-patch <source-tag> 
4

La manera más fácil es para usar git diff, un y agregue git log si desea el mensaje de compromiso combinado que arrojaría el método squash. Por ejemplo, para crear el parche entre cometer abcd y 1234:

git diff abcd..1234 > patch.diff 
git log abcd..1234 > patchmsg.txt 

A continuación, al aplicar la revisión:

git apply patch.diff 
git add -A 
git reset patch.diff patchmsg.txt 
git commit -F patchmsg.txt 

No se olvide el argumento --binary a git diff cuando se trata de archivos no son de texto, p.ej imágenes o videos.

Cuestiones relacionadas