2011-08-04 27 views
288

Tengo un montón de commits en mi repositorio local que son temáticamente similares. Me gustaría combinarlos en una única confirmación antes de pasar a un control remoto. ¿Cómo lo hago? Creo que rebase hace esto, pero no puedo entender los documentos.Combinando múltiples commits antes de presionar en Git

+1

Para rebasar/aplastar un número arbitrariamente grande de commits, ver [mi respuesta a "Squash/combine/rebase un número arbitrariamente grande de confirmaciones"] (http://stackoverflow.com/a/22161885/456814). –

+1

Relacionados [¿Cómo puedo aplastar mis últimas X confirmaciones usando git?] (Http://stackoverflow.com/q/5189560/456814). –

Respuesta

449

Lo que quieres hacer se conoce como "aplastamiento" en git. Hay un montón de opciones cuando usted está haciendo esto (demasiados?), Pero si lo que desea es combinar todas sus confirmaciones unpushed en una única confirmación, haga lo siguiente:

git rebase -i origin/master 

Con ello se abre el editor de texto (-i es para "interactivo") con un archivo que tiene este aspecto:

pick 16b5fcc Code in, tests not passing 
pick c964dea Getting closer 
pick 06cf8ee Something changed 
pick 396b4a3 Tests pass 
pick 9be7fdb Better comments 
pick 7dba9cb All done 

cambian todo el pick a squash (o s), excepto la primera:

pick 16b5fcc Code in, tests not passing 
squash c964dea Getting closer 
squash 06cf8ee Something changed 
squash 396b4a3 Tests pass 
squash 9be7fdb Better comments 
squash 7dba9cb All done 

Guarde su archivo y salga de su editor. Luego, se abrirá otro editor de texto para que pueda combinar los mensajes de confirmación de todas las confirmaciones en un gran mensaje de confirmación.

Voila! Buscar en Google "git squashing" le dará explicaciones de todas las demás opciones disponibles.

+14

Por 'origin/master', ¿quieres decir' '? Si la rama ascendente está configurada, ¿está implícita o debo especificarla todavía? –

+0

Esa es una manera genial de reducir el número de confirmaciones, pero ¿qué ocurre si solo quiero eliminar un subcomito, por ejemplo: eliminar "c964dea Acercándose" a este subcomando en la confirmación, ¿es posible? – Jusleong

+7

Use 'fixup' en lugar de' squash' para omitir el paso de crear un nuevo mensaje de confirmación. El último mensaje de confirmación ("Todo listo") se usará automáticamente para la confirmación final creada por 'rebase'. – faizal

1

Probablemente desee utilizar Interactive Rebasing, que se describe en detalle en ese enlace.

Puede encontrar otros buenos recursos si busca "git rebase interactive".

24

Usted puede hacer esto con git rebase -i, pasando por la revisión que desea utilizar como el 'root':

git rebase -i origin/master 

se abrirá una ventana de edición que muestra todas las confirmaciones que ha hecho después de la última confirmación en origin/master. Puede rechazar commits, squash commits en una única confirmación o editar commits previos.

Hay algunos recursos que probablemente puede explicar esto de una manera mejor, y mostrar algunos otros ejemplos:

http://book.git-scm.com/4_interactive_rebasing.html

y

http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

son los primeros dos buenas páginas Lo podría encontrar.

50

Si tiene mucha de confirmaciones y sólo desea aplastar los últimos X se compromete, encontrar el ID de comprometerse de la confirmación desde el que desea iniciar aplastar y hacer

git rebase -i <that_commit_id> 

A continuación, proceder como se describe en la respuesta de Leopd, cambiar todos los pick a squash es, excepto el primero.

+2

Me tomó un tiempo averiguarlo, pero parece que NO va a ser aplastado. – lznt

+2

Debería decir "encontrar el ID de confirmación de la confirmación justo antes del conjunto de confirmaciones que desea aplastar en una". – BenjaminBallard

10

me ocurrió con

#!/bin/sh 

message=`git log --format=%B origin..HEAD | sort | uniq | grep -v '^$'` 
git reset --soft origin 
git commit -m "$message" 

Cosechadoras, tipo, unifica y eliminar las líneas vacías desde el mensaje de confirmación. Lo uso para cambios locales en un wiki de github (usando gollum)

+0

¡Esta es una idea muy inteligente! – zatziky

+0

Por alguna razón (tal vez es mi configuración o la forma en que uso GIT), origen ... HEAD me dio un error de argumento ambiguo. Para asegurarme de que siempre está obteniendo la diferencia con la cabeza de la rama actual, necesitaba adaptar la primera línea con el 'git log' a esta' git fetch && git log --format =% B FETCH_HEAD..HEAD' [... ] La obtención primero se asegura de que GIT tenga los últimos conocimientos necesarios y crea una referencia FETCH_HEAD que podemos usar. –

3

Puede aplastar (unir) commits con Rebase interactivo. Hay un muy buen video de YouTube que muestra cómo hacer esto en la línea de comandos o con SmartGit:

Si usted ya es un usuario SmartGit continuación, puede seleccionar todas las confirmaciones salientes (manteniendo presionada la tecla Ctrl) y abra el menú contextual (clic derecho) para aplastar sus confirmaciones.

es muy cómodo:

enter image description here

También hay un muy buen tutorial de Atlassian que muestra cómo funciona:

5

y mi forma de squashing múltiple push es (quizás usted empujó a su propia rama muchas confirmaciones y ahora desea hacer una solicitud de extracción y no desea saturarlas con muchas confirmaciones que ya ha enviado). La forma en que hago eso (no hay otra opción más simple, por lo que puedo decir es).

  1. Crear nueva rama en aras de squash (rama de la rama original que desea tirar de solicitud a).
  2. Empuje la rama recién creada.
  3. Merge branch con confirmaciones (ya presionadas) a la nueva rama.
  4. Rebase nueva rama y calabaza.
  5. Push new branch.
  6. Crea una nueva solicitud de extracción para una nueva rama que ahora tiene una confirmación única.

Ejemplo:

git checkout from_branch_you_wish_to_pull_request_to 
git checkout -b new_branch_will_have_single_squashed_commit 
git push -u new_branch_will_have_single_squashed_commit 
git merge older_branch_with_all_those_multiple_commits 
git rebase -i (here you squash) 
git push origin new_branch_will_have_single_squashed_commit 

Ahora puede tirar de solicitud en from_branch_you_wish_to_pull_request_to

20

Hay bastantes pocas respuestas a trabajar aquí, pero he encontrado este el más fácil. Este comando se abrirá un editor, donde sólo se puede reemplazar con picksquash el fin de eliminar/agruparlos en un solo

git rebase -i HEAD~4 

donde, 4 es el número de confirmaciones que desea aplastar en una sola. Esto se explica también en here.