Estoy tratando de fusionar 2 commits en 1, así que seguí "aplastando commits con rebase" desde git ready .
corrí
git rebase --interactive HEAD~2
En el editor resultante, cambio pick
a squash
y luego salvo-salgo, pero el rebase falla con el error
No se puede 'aplastar' sin una confirmación previa
Ahora que mi árbol de trabajo ha alcanzado este estado, tengo problemas para recuperarme.
El comando git rebase --interactive HEAD~2
falla con:
Rebase interactivo ya comenzó
y git rebase --continue
falla con
No se puede 'aplastar' sin una confirmación previa
Respuestas:
Resumen
El mensaje de error
significa que probablemente intentaste "aplastar hacia abajo". Git siempre aplasta una confirmación más nueva en una confirmación más antigua o "hacia arriba" como se ve en la lista interactiva de tareas de rebase, es decir, en una confirmación en una línea anterior. Cambiar el comando en la primera línea de tu lista de tareas
squash
siempre producirá este error, ya que no hay nada en lo que pueda comprometerse el primer commit.La solución
Primero regrese a donde comenzó
Digamos que tu historia es
Es decir, a fue el primer commit, luego b, y finalmente c. Después de cometer c, decidimos aplastar b y c juntos:
(Nota: Ejecutar
git log
canaliza su salida en un buscapersonas,less
de manera predeterminada en la mayoría de las plataformas. Para salir del buscapersonas y volver al símbolo del sistema, presione laq
tecla).Correr
git rebase --interactive HEAD~2
te da un editor con(Tenga en cuenta que esta lista de tareas está en el orden inverso en comparación con la salida de
git log
).Cambiar las b
pick
asquash
resultará en el error que viste, pero si en cambio aplastas c en b (el más nuevo se compromete en el anterior o "aplasta hacia arriba") al cambiar la lista de tareas ay guardar-salir de su editor, obtendrá otro editor cuyos contenidos son
Cuando guarda y sale, el contenido del archivo editado se convierte en mensaje de confirmación de la nueva confirmación combinada:
Nota sobre la reescritura del historial
El rebase interactivo reescribe la historia. Intentar pasar a un control remoto que contiene el historial anterior fallará porque no es un avance rápido.
Si la rama que usted reformuló es una rama de tema o característica en la que está trabajando solo , no es gran cosa. Empujar a otro repositorio requerirá la
--force
opción, o alternativamente, según los permisos del repositorio remoto, es posible que pueda eliminar primero la rama anterior y luego empujar la versión modificada. Los ejemplos de esos comandos que potencialmente destruirán el trabajo están fuera del alcance de esta respuesta.Reescribir el historial ya publicado en una rama en la que está trabajando con otras personas sin una muy buena razón, como filtrar una contraseña u otros detalles confidenciales, obliga a sus colaboradores a trabajar y es antisocial y molestará a otros desarrolladores. La sección "Recuperación de una base de datos ascendente" en la
git rebase
documentación explica, con énfasis adicional.fuente
git log hashoftheoldcommit
y funcionó, pero tenía curiosidad por ver unagit log --graph
con todas estas confirmaciones inalcanzables incluidasSi hay varias confirmaciones, puede usar
git rebase -i
para aplastar dos confirmaciones en una.Si solo hay dos confirmaciones que desea fusionar, y son las "dos más recientes", los siguientes comandos se pueden usar para combinar las dos confirmaciones en una:
fuente
git reset --soft HEAD~10
, donde 10 es el número de confirmaciones que desea fusionar.HEAD
usandogit reset --soft 47b5c5...
, donde47b5c5...
es el ID SHA1 de la confirmación.Rebase: No lo vas a necesitar:
Una forma más sencilla para el escenario más frecuente.
En la mayoría de los casos:
En realidad, si todo lo que quiere es simplemente combinar varias confirmaciones recientes en una, pero no necesita
drop
,reword
y otro trabajo de rebasesimplemente puedes hacer:
~n
es el número de confirmaciones a suavemente un-commit (es decir~1
,~2
, ...)Luego, use el siguiente comando para modificar el mensaje de confirmación.
que es casi lo mismo que un largo rango de
squash
y unopick
.Y funciona para n commits pero no solo para dos commits como se indica en la respuesta anterior.
fuente
~n
es el número de confirmaciones a suavemente un-commit (es decir~1
,~2
, ...)n
últimas confirmaciones, sino lasn
confirmaciones en el medio? ¿Puedo hacer eso fácilmente?git rebase -i
es lo que necesitas parasquash
trabajar. @chumakoffn
los commits más recientes en un primer usogit reset --soft @~m
, dondem = n - 1
Primero debe verificar cuántas confirmaciones tiene:
Hay dos estados:
Una es que solo hay dos confirmaciones:
Por ejemplo:
(En este caso, no puede usar git rebase para hacer) debe hacer lo siguiente.
Otra es que hay más de dos commits; desea fusionar commit C y D.
Por ejemplo:
(bajo esta condición, puede usar git rebase)
Y que usar "squash" para hacer. El resto es muy fácil. Si aún no lo sabe, lea http://zerodie.github.io/blog/2012/01/19/git-rebase-i/
fuente
git push -f origin master
podría ser necesario.Suponiendo que estuvieras en tu propia rama temática. Si desea fusionar los últimos 2 commits en uno y parecerse a un héroe, ramifique el commit justo antes de realizar los últimos dos commits.
Luego, squash confirma la otra rama en esta nueva rama:
Eso traerá los cambios pero no los comprometerá. Así que solo confía en ellos y listo.
Ahora puede fusionar esta nueva rama de tema nuevamente en su rama principal.
fuente
a
yc
requiere que se fusionen entre sí y mantenerb
tal cual es.git checkout -b combine-last-two-commits "HEAD^2"
) en git versión 2.17,fatal: 'HEAD^2' is not a commit and a branch 'combine-last-two-commits' cannot be created from it
puedes cancelar el rebase con
y cuando ejecutas el comando de rebase interactivo nuevamente, 'squash; commit debe estar debajo del pick commit en la lista
fuente
A menudo uso git reset --mixed para revertir una versión base antes de múltiples commits que desea fusionar, luego hago un nuevo commit, de esa manera podría permitir que su commit sea más nuevo, asegúrese de que su versión sea HEAD después de presionar al servidor.
Si quiero fusionar head dos commits en uno, primero uso:
"249cf9392da197573a17c8426c282" era la tercera versión, también es su versión base antes de fusionarse, después de eso, hago una nueva confirmación:
Es todo, la esperanza es otra forma para todos.
FYI, de
git reset --help
:fuente
$ git rebase --abort
Ejecute este código en cualquier momento si desea deshacer el git rebase
$ git rebase -i HEAD~2
Para volver a aplicar las dos últimas confirmaciones. El comando anterior abrirá un editor de código
Después: wq estará en modo de rebase activo
Nota : Obtendrá otro editor si no hay mensajes de advertencia / error. Si hay un error o una advertencia que no se mostrará otro editor, puede cancelar ejecutando
$ git rebase --abort
si ve un error o advertencia, de lo contrario, simplemente continúe ejecutando$ git rebase --continue
Verá su mensaje de confirmación 2. Elija uno o escriba su propio mensaje de confirmación, guarde y salga [: wq]
Nota 2: es posible que deba forzar los cambios al repositorio remoto si ejecuta el comando rebase
$ git push -f
$ git push -f origin master
fuente
git push -f origin/master
es lo que faltan otras respuestas. +1Desde que uso
git cherry-pick
para casi todo, para mí es natural hacerlo incluso aquí.Dado que me he
branchX
retirado y hay dos confirmaciones en la punta, de las cuales quiero crear una confirmación combinando su contenido, hago esto:Si quiero actualizar
branchX
también (y supongo que este es el lado negativo de este método) también tengo que:fuente
Si su rama maestra se
git log
parece a la siguiente:y desea fusionar las dos confirmaciones principales, simplemente siga estos sencillos pasos:
git checkout 77df2a40e53136c7a2d58fd847372 -b merged-commits
git cherry-pick -n -x ac72a4308ba70cc42aace47509a5e
. (Resolver conflictos si surge alguno)git commit --amend
.Eso es. Puede insertar esta versión fusionada en la rama "merged-commits" si lo desea.
Además, ahora puede descartar las dos confirmaciones consecutivas en su rama maestra. Simplemente actualice su rama maestra como:
fuente
Si desea combinar las dos confirmaciones más recientes y simplemente usar el mensaje de la confirmación anterior, puede automatizar el proceso utilizando
expect
.Asumo:
Lo probé con
git version 2.14.3 (Apple Git-98)
.fuente
expect
está sin describir.expect
.