¿Cómo arreglar el compromiso con la rama Git incorrecta?

621

Acabo de hacer un compromiso perfectamente bueno con la rama equivocada. ¿Cómo deshago la última confirmación en mi rama maestra y luego tomo los mismos cambios y los incluyo en mi rama de actualización?

Mikewilliamson
fuente

Respuestas:

975

Si aún no ha presionado sus cambios, también puede hacer un restablecimiento parcial:

git reset --soft HEAD^

Esto revertirá la confirmación, pero volverá a colocar los cambios confirmados en su índice. Suponiendo que las ramas estén relativamente actualizadas entre sí, git le permitirá realizar un pago en la otra rama, con lo que simplemente puede comprometerse:

git checkout branch
git commit

La desventaja es que debe volver a ingresar su mensaje de confirmación.

Blair Holloway
fuente
10
tenga en cuenta que el restablecimiento parcial deja sus cambios preparados y listos para confirmar. Me confundí un poco cuando mi IDE no mostró que los archivos volvieran al estado modificado después del restablecimiento parcial.
mtjhax
99
solución perfecta, en realidad tuve un par de compromisos, así que HEAD ^^ y bam all is gravy
pablo
8
Gracias. Esto me ha salvado dos veces. Si las ramas son algo diferentes, después del reinicio y antes del pago, puede que tenga que esconder sus cambios antes de poder pagar otra rama. Vuelva a aplicar el alijo después del pago
Kirby
17
Usuarios de zsh: es posible que necesiten escapar del ^ así:git reset --soft HEAD\^
Stephen Fuhry
54
Si obtienes más? en la línea de comandos de Windows, use comillas para rodear HEAD ^ así: git reset --soft "HEAD ^"
Nate Cook
142

4 años de retraso en el tema, pero esto podría ser útil para alguien.

Si olvidó crear una nueva rama antes de comprometerse y se comprometió todo en master, no importa cuántas confirmaciones haya hecho, el siguiente enfoque es más fácil:

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

Ahora tiene su rama maestra igual origin/mastery todas las nuevas confirmaciones están activadas my_feature. Tenga en cuenta que my_featurees una sucursal local, no remota.

fotanus
fuente
Gracias por la respuesta. Ahora estoy usando egit y me pregunto si puedo lograr lo mismo haciendo lo siguiente: 1) Cambie el nombre del 'maestro' actual a 'my_feature'. 2) Recrea el 'maestro' local desde 'origen / maestro'. No estoy seguro de qué está haciendo egit bajo el capó para estas operaciones, pero esta parece ser una solución viable
mjj1409
¿Por qué la fusión? se podría crear la rama directamente sobre masterel problema, restablezca mastera origin/master.
caesarsol
1
Esa es la parte más interesante: no necesita una cantidad de confirmación, porque origin/masterya está en la confirmación que desea restablecer. Sin embargo, el crédito por la propina es esta página: github.com/blog/…
caesarsol
44
Esta debería ser la respuesta aceptada. Simple, obvio, directo, funciona independientemente del número de confirmaciones y solo usa la funcionalidad básica de Git. Hice estos pasos con TortoiseGit. ¡Gracias! :)
Ian Grainger
1
Pensé que esta era la mejor respuesta, pero tiene una limitación. Solo ayuda si recientemente sacó del control remoto. Y supone que tiene un control remoto para comenzar. Si solo tiene sucursales locales "maestras" y su nueva función corregida, la única respuesta correcta es un restablecimiento completo en maestro contando un cierto número de confirmaciones.
pauljohn32
111

Si tiene una copia de trabajo limpia (sin modificar)

Para revertir una confirmación (asegúrese de anotar el hash de la confirmación para el siguiente paso):

git reset --hard HEAD^

Para llevar esa confirmación a una rama diferente:

git checkout other-branch
git cherry-pick COMMIT-HASH

Si tiene cambios modificados o sin seguimiento

También tenga en cuenta que git reset --hardva a matar a cualquier cambio sin seguimiento y modificados que pueda tener, por lo que si usted tiene los es posible que prefiera:

git reset HEAD^
git checkout .
Michael Mrozek
fuente
git rev-parse BRANCH_NAMEpara conseguir el sha
wilhelmtell
12
Si olvida anotar el hash primero, ¡solo use git reflog show <branch>!
Cascabel
2
@Jefromi Me asusté por un minuto.
Ian Hunter
13
Para una sensación de seguridad adicional, realice la selección de cereza primero en la rama correcta y solo luego restablezca la rama incorrecta.
Edad Mooij
1
También en caso de cambios no rastreados, uno puede git stashantes del reinicio y usar git stash popdespués para restaurarlos, por lo que no hay que tenerle miedo a la --hardparte
Clemens Klein-Robbenhaar
20

Si ya presionó sus cambios, deberá forzar su próximo empuje después de reiniciar el HEAD.

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

Advertencia: un restablecimiento completo deshacerá cualquier modificación no confirmada en su copia de trabajo, mientras que un empuje forzado sobrescribirá completamente el estado de la rama remota con el estado actual de la rama local.

Por si acaso, en Windows (usando la línea de comando de Windows, no Bash) en realidad es cuatro en ^^^^lugar de uno, por lo que es

git reset --hard HEAD^^^^
Igor Zevaka
fuente
66
Tenga en cuenta que usted debe no forzar la inserción a una rama que otras personas están usando menos que sea absolutamente necesario - de lo contrario no será capaz de empujar hasta que rebase. Sin embargo, si usted es el único desarrollador que usa git, está bien.
Blair Holloway
2
O a menos que se dé cuenta lo suficientemente rápido antes de que alguien más haya realizado las confirmaciones erróneas.
Michael Mior
Si se compromete más de uno, puede especificar el compromiso que necesita: git reset --hard COMMIT_HASH git push --force
David Cramblett
17

Recientemente hice lo mismo, donde accidentalmente cometí un cambio en master, cuando debería haberme comprometido con otra rama. Pero no presioné nada.

Si acaba de comprometerse con la rama equivocada, y no ha cambiado nada desde entonces, y no ha enviado al repositorio, puede hacer lo siguiente:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

NOTA: en el ejemplo anterior, estaba rebobinando 1 commit con git reset HEAD ~ 1. Pero si desea rebobinar n commits, puede hacer git reset HEAD ~ n.

Además, si terminó comprometiéndose con la rama incorrecta, y también terminó escribiendo más código antes de darse cuenta de que se comprometió con la rama incorrecta, entonces podría usar git stash para guardar su trabajo en progreso:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

NOTA: Usé este sitio web como referencia https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/

Ali Mizan
fuente
Me sucedió algo similar, cometí algunos cambios en el master, pero debería haberlo hecho en una nueva sucursal y enviar relaciones públicas, terminé haciendo un git checkout -b new_branchderecho desde allí, las confirmaciones estaban intactas, solo presioné y creé un PR, no lo hice No tengo que comprometerme de nuevo.
Nishchal Gautam
11

Entonces, si su escenario es con el que se comprometió masterpero con el que se comprometió another-branch(que puede o no existir) pero aún no lo ha hecho, esto es bastante fácil de solucionar.

// if your branch doesn't exist, then add the -b argument 
git checkout -b another-branch
git branch --force master origin/master

Ahora todos tus compromisos masterestarán activos another-branch.

Fuente de amor de: http://haacked.com/archive/2015/06/29/git-migrate/

Lorcan O'Neill
fuente
¡Parece ser el enfoque más directo! No estoy seguro de por qué tan poco amor y upwotes
keligijus
44
Esto no pareció funcionar para mí. another-branchYa existía. En este caso, simplemente destruyó los compromisos que hice para dominar y no los ejecuté another-branch.
Giselle Serate
6

Para elaborar esta respuesta, en caso de que tenga varias confirmaciones para pasar de, por ejemplo, developa new_branch:

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started
arsenio
fuente
1
Tenía tres compromisos para revertir, y esta pregunta parece haber sacado mi trasero del fuego. ¡Gracias!
holdenweb
3

Si se encuentra con este problema y tiene Visual Studio, puede hacer lo siguiente:

Haga clic derecho en su rama y seleccione View History:

ingrese la descripción de la imagen aquí

Haga clic derecho en commit al que desea volver. Y revertir o restablecer según sea necesario.

ingrese la descripción de la imagen aquí

Trevor
fuente
3

Para confirmaciones múltiples en la rama incorrecta

Si para usted, se trata solo de 1 commit, entonces hay muchas otras soluciones de restablecimiento más fáciles disponibles. Para mí, tuve alrededor de 10 confirmaciones hechas accidentalmente en masterlugar de, llamémoslo branch_xyz, y no quería perder el historial de confirmaciones.

Lo que podía hacer y lo que me salvó fue usar esta respuesta como referencia, usando un proceso de 4 pasos, que es:

  1. Crear una nueva rama temporal desde master
  2. Fusionarse en la rama originalmente destinada a confirmaciones, es decir branch_xyz
  3. Deshacer se compromete en master
  4. Eliminar la rama temporal.

Aquí están los pasos anteriores en detalles:

  1. Crear una nueva rama desde master(donde accidentalmente cometí muchos cambios)

    git checkout -b temp_branch_xyz
    

    Nota: la -bbandera se usa para crear una nueva rama.
    Solo para verificar si lo hicimos bien, haría un rápido git branchpara asegurarme de que estamos en la temp_branch_xyzrama y una git logpara verificar si tenemos los compromisos correctos.

  2. Combinar la rama temporal en la rama originalmente destinada para los commits, es decir branch_xyz.
    Primero, cambie a la rama original, es decir branch_xyz(es posible que deba hacerlo git fetchsi no lo ha hecho)

    git checkout branch_xyz
    

    Nota: Sin usar el -bindicador
    Ahora, fusionemos la rama temporal en la rama que tenemos actualmente retiradabranch_xyz

    git merge temp_branch_xyz
    

    Puede que tenga que ocuparse de algunos conflictos aquí, si los hay. Puede presionar (lo haría) o pasar a los siguientes pasos, después de fusionar con éxito.

  3. Deshaga las confirmaciones accidentales al masterusar esta respuesta como referencia, primero cambie amaster

    git checkout master
    

    luego deshaga todo el camino para que coincida con el control remoto (o para confirmar en particular, si lo desea)

    git reset --hard origin/master
    

    Nuevamente, haría un git logantes y un después solo para asegurarme de que los cambios previstos surtieran efecto.

  4. Borrar la evidencia, eso es borrar la rama temporal. Para esto, primero debe verificar la rama en la que se fusionó la temperatura, es decir branch_xyz(si permanece encendido mastery ejecuta el siguiente comando, puede obtener un error: The branch 'temp_branch_xyz' is not fully merged), así que vamos a

    git checkout branch_xyz
    

    y luego elimine la prueba de este contratiempo

    git branch -d temp_branch_xyz
    

Ahí tienes.

Mitali Cyrus
fuente
1

Si la rama a la que desea aplicar sus cambios ya existe ( desarrollo de la rama , por ejemplo), siga las instrucciones proporcionadas por fotanus a continuación, luego:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

Y, obviamente, podría usar tempbranch o cualquier otro nombre de rama en lugar de my_feature si lo desea.

Además, si corresponde, retrase el stash pop (aplicar) hasta que se haya fusionado en su rama de destino.

fbicknel
fuente
Creo que el primer comando (checkout desarrollo) es innecesario ... el rebase simplemente pagará "my_feature" como lo primero que hace.
JoelFan
También puede omitir el parámetro "my_feature" del comando "rebase" (ya que ha desprotegido "my_feature"). también puede omitir el parámetro "desarrollo" de la "fusión" (ya que desprotege "desarrollar")
JoelFan
1

Para mí, esto se resolvió revirtiendo el compromiso que había presionado, y luego seleccionando ese compromiso para la otra rama.

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

Puede usar git logpara encontrar el hash correcto, ¡y puede impulsar estos cambios cuando lo desee!

arr0nax
fuente