¿Cómo aplastar los commits en git después de que hayan sido presionados?


551

Esto da una buena explicación de aplastar múltiples confirmaciones:

http://git-scm.com/book/en/Git-Branching-Rebasing

pero no funciona para confirmaciones que ya se han enviado. ¿Cómo elimino las últimas confirmaciones tanto en mis repositorios locales como remotos?

EDITAR: cuando lo haga git rebase -i origin/master~4 master, mantenga el primero como pick, configure los otros tres como squashy luego salga (a través de cx cc en emacs), obtengo:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

donde 2f40 es el pickcommit. Y ahora no aparece ninguno de los 4 commits git log. Esperaba que mi editor se reiniciara para poder ingresar un mensaje de confirmación. ¿Qué estoy haciendo mal?

Respuestas:


781

Squash se compromete localmente con

git rebase -i origin/master~4 master

y luego forzar el empuje con

git push origin +master

Diferencia entre --forcey+

De la documentación de git push:

Tenga en cuenta que se --forceaplica a todas las referencias que se envían, por lo tanto, usarlo con push.defaultset to matchingo con múltiples destinos de inserción configurados con remote.*.pushpuede sobrescribir referencias que no sean la rama actual (incluidas las referencias locales que están estrictamente detrás de su contraparte remota). Para forzar un empuje a una sola rama, use un + frente de la especificación de referencia para empujar (por ejemplo, git push origin +masterpara forzar un empuje a la masterrama).


30
también puedesgit push --force origin master
— Daenyth

77
Daenyth : Sí, pero siempre prefiero esta sintaxis ya que es más corta.
— Alan Haggai Alavi

86
Y, por supuesto, tenga en cuenta que si alguien más podría haberse retirado del repositorio remoto, probablemente no quiera hacer esto; la respuesta en ese caso es "no".
— Cascabel

10
Además, creo que el OP está copiando exactamente el comando git rebase -i origin/master, y en realidad quiere saber cómo volver a crear los commits más atrás que eso, por ejemplo git rebase -i origin/master~20 master.
— Cascabel

66
gstackoverflow :+fuerza solo la refspec que tiene el prefijo. --forceobligará a todas las especificaciones a ser empujadas. Por favor vea la respuesta actualizada.
— Alan Haggai Alavi

120

En una sucursal pude hacerlo así (durante los últimos 4 commits)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch

1
Hacer esto con el comando suave en una rama ya presionada terminó presionando a un montón de otras personas comprometidas por mí.
— cchamberlain

3
Una tonelada? ¿Cómo puede ser más de 4? ¿Puedes elaborar?
— jakob-r

De eso no estoy seguro, pero tenía algo que ver con tratar de aplastar un commit ya empujado. Parece que otros experimentaron algo similar aquí - stackoverflow.com/questions/5189560/…
— cchamberlain

44
Hubiera aceptado esto como respuesta esperada. Más limpio que aceptó la respuesta.
— vikramvi

44
Esta es la respuesta más clara y aceptada en solo 4 pasos
— Ameya Salagre

45

Diferencia menor a la respuesta aceptada, pero estaba teniendo muchas dificultades para aplastar y finalmente lo obtuve.

$ git rebase -i HEAD~4
  • En la pantalla interactiva que se abre, reemplace pick con squash en la parte superior para todas las confirmaciones que desea aplastar.
  • Guarde y cierre el editor a través de esc --> :wq

Empuje al control remoto usando:

$ git push origin branch-name --force

2
breve y eficaz, elaborado:
— terwxqian

22

Se pueden evitar muchos problemas creando solo una branchpara trabajar y no trabajando master:

git checkout -b mybranch

Lo siguiente funciona para remoteconfirmaciones ya enviadas y una mezcla de remoteconfirmaciones enviadas / localsolo confirmaciones:

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

También tengo algunas notas de solicitud de extracción que pueden ser útiles.


17

git rebase -i master

obtendrá el editor vm abierto y msgs algo como esto

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

Aquí he cambiado la selección de todos los otros commits a "f" (significa reparación).

git push -f origin feature/feature-branch-name-xyz

esto arreglará todas las confirmaciones en una confirmación y eliminará todas las demás confirmaciones. Hice esto y me ayudó.


3

Cuando trabajas con un Gitlab o Github, puedes tener problemas de esta manera. Aplasta tus commits con uno de los métodos anteriores. Mi preferido es:

git rebase -i HEAD~4
or
git rebase -i origin/master

seleccione squash o arreglo para su compromiso. En este punto, debería verificar el estado de git. Y el mensaje podría ser:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

Y puedes tener la tentación de tirar de él. NO HAGAS ESO o estarás en la misma situación que antes.

En su lugar, empuje a su origen con:

git push origin +ABC-1916-remote:ABC-1916

El + permite forzar el empuje solo a una rama.


no hay nada de malo en tirar, especialmente si tienes conflictos, se pueden resolver más fácilmente que si fuerzas el empuje
— Ray_Poly

2

Para aplastar dos commits, uno de los cuales ya fue empujado, en una sola rama funcionó lo siguiente:

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

Por defecto, esto incluirá el mensaje de confirmación de la confirmación más reciente como un comentario sobre la confirmación más antigua.


2

1) git rebase -i HEAD~4

Para elaborar: Funciona en la rama actual; HEAD ~ 4 significa aplastar los últimos cuatro commits; modo interactivo (-i)

2) En este punto, el editor abrió, con la lista de confirmaciones, para cambiar las segundas y siguientes confirmaciones, reemplazando pick con squash y luego guárdelo.

salida: referencias y cabezas / nombre de sucursal actualizadas y actualizadas correctamente.

3) git push origin refs/heads/branch-name --force

salida:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.