En una de mis ramas de desarrollo, hice algunos cambios en mi código base. Antes de poder completar las características en las que estaba trabajando, tuve que cambiar mi rama actual a master para demostrar algunas características. Pero sólo usando un "git checkout master" conservó los cambios que también hice en mi rama de desarrollo, rompiendo así algunas de las funcionalidades en master. Así que lo que hice fue confirmar los cambios en mi rama de desarrollo con un mensaje de confirmación "temporal commit" y luego checkout maestro para la demostración.
Ahora que he terminado con la demostración y volver a trabajar en mi rama de desarrollo, me gustaría eliminar el "commit temporal" que hice, mientras que todavía conserva los cambios que hice. ¿Es posible?
Es tan sencillo como esto:
git reset HEAD^
git reset
sin un --hard
o --soft
mueve tu HEAD
para que apunte al commit especificado, sin cambiar ningún archivo. La "cabeza" se refiere al (primer) commit padre de tu commit actual, que en tu caso es el commit anterior al temporal.
Tenga en cuenta que otra opción es continuar de forma normal, y luego en el siguiente punto de confirmación en su lugar ejecutar:
git commit --amend [-m … etc]
que en su lugar editará la confirmación más reciente, teniendo el mismo efecto que el anterior.
Ten en cuenta que esto (como con casi todas las respuestas de git) puede causar problemas si ya has empujado el commit malo a un lugar de donde alguien más puede haberlo sacado. Intenta evitar eso
Hay dos maneras de manejar esto. La más fácil depende de su situación
Reiniciar
Si el commit del que quieres deshacerte fue el último commit, y no has hecho ningún trabajo adicional puedes simplemente usar git-reset
.
git reset HEAD^
Lleva tu rama de vuelta al commit justo antes de tu HEAD actual. Sin embargo, en realidad no cambia los archivos en su árbol de trabajo. Como resultado, los cambios que estaban en ese commit aparecen como modificados - es como un comando 'uncommit'. De hecho, tengo un alias para hacer precisamente eso.
git config --global alias.uncommit 'reset HEAD^'
Entonces puedes usar git uncommit
en el futuro para respaldar un commit.
Cascarilla
Aplastar una confirmación significa combinar dos o más confirmaciones en una. Yo hago esto muy a menudo. En tu caso tienes una característica a medio hacer confirmada, y entonces la terminarías y la confirmarías de nuevo con el mensaje de confirmación apropiado y permanente.
git rebase -i <ref>
Delante de cada confirmación, tendrá la palabra "pick". Encuentre la confirmación de la que quiere deshacerse y cámbiela de pick
a fixup
o squash
. Usar fixup
simplemente descarta ese mensaje de confirmación y fusiona los cambios con su predecesor inmediato en la lista. La palabra clave squash
hace lo mismo, pero le permite editar el mensaje de confirmación de la nueva confirmación combinada.
Tenga en cuenta que las confirmaciones serán re-comprometidas en el orden en que aparecen en la lista cuando salga del editor. Así que si usted hizo una confirmación temporal, luego hizo otro trabajo en la misma rama, y completó la característica en una confirmación posterior, entonces el uso de rebase le permitiría reordenar las confirmaciones y aplastarlas.
AVISO:
Rebasar modifica el historial - NO hagas esto a ningún commit que ya hayas compartido con otros desarrolladores.
Stashing
En el futuro, para evitar este problema, considere el uso de git stash
para almacenar temporalmente el trabajo no comprometido.
git stash save 'some message'
Esto almacenará tus cambios actuales en tu lista de stash. Esta es la versión más explícita del comando stash, que permite un comentario para describir lo que se está almacenando. También puedes ejecutar simplemente git stash
y nada más, pero no se almacenará ningún mensaje.
Puedes navegar por tu lista de stash con...
git stash list
Esto te mostrará todos tus stashes, en qué ramas se hicieron, y el mensaje y al principio de cada línea, y el identificador para ese stash que se parece a esto stash@{#}
donde # es su posición en el array de stashes.
Para restaurar un stash (que se puede hacer en cualquier rama, independientemente de dónde se creó originalmente el stash) simplemente se ejecuta...
git stash apply stash@{#}
De nuevo, ahí # está la posición en el array de stashes. Si el stash que quieres restaurar está en la posición 0
- es decir, si era el stash más reciente. Entonces puedes ejecutar el comando sin especificar la posición del stash, git asumirá que te refieres al último: git stash apply
.
Así, 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 has movido un poco más por las ramas, pero la misma idea sigue siendo válida.
Espero que esto ayude.