¿Puedo eliminar una confirmación de git pero conservar los cambios?

Resuelto tanookiben asked hace 11 años • 13 respuestas

En una de mis ramas de desarrollo, hice algunos cambios en mi código base. Antes de poder completar las funciones en las que estaba trabajando, tuve que cambiar mi rama actual a master para demostrar algunas funciones. Pero el simple hecho de usar un "git checkout master" conservó los cambios que también hice en mi rama de desarrollo, rompiendo así algunas de las funciones en master. Entonces, lo que hice fue confirmar los cambios en mi rama de desarrollo con un mensaje de confirmación "compromiso temporal" y luego verificar la demostración.

Ahora que terminé con la demostración y volví a trabajar en mi rama de desarrollo, me gustaría eliminar el "compromiso temporal" que hice y al mismo tiempo conservar los cambios que hice. ¿Es eso posible?

tanookiben avatar Apr 03 '13 01:04 tanookiben
Aceptado

Es tan simple como esto:

git reset HEAD^

Nota: algunos shells se tratan ^como un carácter especial (por ejemplo, algunos shells de Windows o ZSH con globbing habilitado ), por lo que es posible que tengas que citar "HEAD^"o usar HEAD~1en esos casos.

git resetsin --hardo --softmueve su HEADpara que apunte a la confirmación especificada, sin cambiar ningún archivo. HEAD^se refiere a la (primera) confirmación principal de su confirmación actual, que en su caso es la confirmación anterior a la temporal.

Tenga en cuenta que otra opción es continuar normalmente y luego, en el siguiente punto de confirmación, ejecutar:

git commit --amend [-m … etc]

que en su lugar editará la confirmación más reciente, teniendo el mismo efecto que el anterior.

Tenga en cuenta que esto (como ocurre con casi todas las respuestas de git) puede causar problemas si ya envió el compromiso incorrecto a un lugar del que otra persona pudo haberlo extraído. trata de evitar eso

Gareth avatar Apr 02 '2013 18:04 Gareth

Hay dos formas de manejar esto. Lo que es más fácil depende de tu situación.

Reiniciar

Si la confirmación de la que desea deshacerse fue la última confirmación y no ha realizado ningún trabajo adicional, simplemente puede usargit-reset

git reset HEAD^

Lleva su rama nuevamente al compromiso justo antes de su HEAD actual. Sin embargo, en realidad no cambia los archivos en su árbol de trabajo. Como resultado, los cambios que había en esa confirmación se muestran como modificados; es como un comando de "desconfirmación". De hecho, tengo un alias para hacer precisamente eso.

git config --global alias.uncommit 'reset HEAD^'

Luego puede usarlo git uncommiten el futuro para hacer una copia de seguridad de una confirmación.

aplastamiento

Aplastar un compromiso significa combinar dos o más compromisos en uno. Hago esto con bastante frecuencia. En su caso, tiene una función a medio hacer comprometida, y luego la terminaría y la confirmaría nuevamente con el mensaje de confirmación permanente adecuado.

git rebase -i <ref>

Digo lo anterior porque quiero dejar en claro que esto podría ser cualquier número de confirmaciones. Ejecute git logy busque la confirmación de la que desea deshacerse, copie su SHA1 y úsela en lugar de <ref>. Git lo llevará al modo de rebase interactivo. Mostrará todas las confirmaciones entre su estado actual y lo que haya puesto en lugar de <ref>. Entonces, si <ref>hace 10 confirmaciones, le mostrará las 10 confirmaciones.

Delante de cada confirmación, tendrá la palabra pick. Busque la confirmación de la que desea deshacerse y cámbiela de picka fixupo squash. El uso fixupsimplemente descarta ese mensaje de confirmación y fusiona los cambios con su predecesor inmediato en la lista. La squashpalabra clave hace lo mismo, pero le permite editar el mensaje de confirmación de la confirmación recién combinada.

Tenga en cuenta que las confirmaciones se volverán a confirmar en el orden en que aparecen en la lista cuando salga del editor. Entonces, si realizó una confirmación temporal, luego realizó otro trabajo en la misma rama y completó la función en una confirmación posterior, entonces usar rebase le permitirá reordenar las confirmaciones y aplastarlas.

ADVERTENCIA:

El cambio de base modifica el historial: NO hagas esto con ninguna confirmación que ya hayas compartido con otros desarrolladores.

Escondite

En el futuro, para evitar este problema, considere utilizarlo git stashpara almacenar temporalmente el trabajo no comprometido.

git stash save 'some message'

Esto almacenará sus cambios actuales a un lado de su lista de almacenamiento. Arriba está la versión más explícita del comando stash, que permite un comentario para describir lo que estás ocultando. También puedes simplemente ejecutar git stashy nada más, pero no se almacenará ningún mensaje.

Puedes explorar tu lista de alijo con...

git stash list

Esto le mostrará todos sus alijos, en qué ramas se realizaron, el mensaje y al principio de cada línea, y el identificador de ese alijo que se ve así, stash@{#}donde # es su posición en la matriz de alijos.

Para restaurar un alijo (lo que se puede hacer en cualquier rama, independientemente de dónde se creó originalmente) simplemente ejecuta...

git stash apply stash@{#}

Nuevamente, # es la posición en la matriz de escondites. Si el alijo que desea restaurar está en la 0posición, es decir, si era el alijo más reciente. Luego puede simplemente ejecutar el comando sin especificar la posición del alijo, git asumirá que se refiere al último: git stash apply.

Entonces, por ejemplo, si me encuentro trabajando en la rama equivocada, puedo ejecutar la siguiente secuencia de comandos.

git stash
git checkout <correct_branch>
git stash apply

En tu caso te moviste un poco más por las ramas, pero se sigue aplicando la misma idea.

eddiemoya avatar Apr 03 '2013 03:04 eddiemoya