2010-12-14 27 views
16

La situación: Comenzando con el maestro en A ramifiqué e hice algunos cambios en B y luego fusioné esa rama en (C). Después de hacer algunos cambios más, estaba en el D, pero me di cuenta de que necesitaba implementar el código sin los cambios que ocurrieron en la rama. Si no lo hubiera fusionado, hubiera estado bien.Git: Cómo "deshacer" una fusión

A_______C___D 
\ /
    \_B_/ 

En primer lugar me gustaría saber lo que debería haber hecho desde aquí para desplegar el código como si la fusión nunca ocurrió. Nota: ninguno de los mismos archivos que fueron editados en la rama se han editado en el maestro.

En segundo lugar ...

yo no tenía tiempo para elaborar el mejor método para hacer frente a esto, por lo que he eliminado los archivos que se sumó la rama, y ​​de forma manual invertí unos pocos cambios realizados en la rama continuación, comprometido el resultado para el despliegue (F)

A_______C___D___F 
\ /
    \_B_/ 

Quiero ser capaz de mantener el desarrollo de la rama y fusionar los cambios del maestro en él para mantenerlo al día, pero si lo hago que las cosas que hice para crear F se fusionarán y harán que los archivos se eliminen y las ediciones se reviertan. ¿Cuál es la mejor manera de lidiar con esto?

Respuesta

16

Puede utilizar rebase de hacerlo en un solo paso:

git rebase --onto A C D 

Acabo de probar esto, con resultados adecuados:

$ edit test.txt 
$ git add . 
$ git commit -mA 
$ git checkout -b the_branch 
$ edit test.txt 
$ git commit -a -mB 
$ git checkout master 
$ git merge master the_branch --no-ff 
$ edit test.txt 
$ git commit -a -mD 

Desde aquí se tiene la situación que describes. Entonces :

$ git rebase --onto <SHA1-for-A> <SHA1-for-C> master 

rebases comete entre C (excluido) a dominar, en A. que necesitaba para solucionar algunos conflictos ya he modificado en los mismos lugares en B y D, pero creo que no lo hará.

_D' 
/
/
A_______C___D 
\ /
    \_B_/ 

Doc sobre git rebase --onto, que es más o menos su situación: http://git-scm.com/docs/git-rebase


Si tuviera:

A_______C___D___F 
\ /
    \_B_/ 

, a continuación, que tiene ahora:

_D'___F'_(master) 
/
/
A_______C___D___F 
\ /
    \_B_/(the_branch) 

A partir de aquí, fusionar los cambios en el maestro en la sucursal es fácil. Descarte la confirmación F' en total.

$ git checkout master # if you were not here already 
$ git branch old_fix # if you want to be able to return to F' later 
$ git reset --hard <SHA1-to-D'> 

Después de los comandos anteriores se tienen:

 (master) 
    /
    _D'___F'_(old_fix) 
/
/
A_______C___D___F 
\ /
    \_B_/(the_branch) 

combinar las actualizaciones de maestro en the_branch:

$ git checkout the_branch 
$ git merge master 

... y fijar los conflictos.

+0

¡Increíble, gracias! Lo usaré en el futuro (si no funciona, ser más cuidadoso con mis fusiones). Ver la respuesta de @terminus por lo que hice. Creo que logró el mismo resultado que tu respuesta. – Jake

6

La solución obvia es reiniciar a A, vuelva a aplicar todos los parches manualmente y resuelva los conflictos (que no tendrá).

O bien puede simplemente git revert parche B pero eso creará una nueva confirmación.

Aunque la respuesta de Gauthier es mejor.

+0

Gracias, después de leer esto, busqué parches y terminé aquí: http://www.gitready.com/intermediate/2009/03/04/pick-out-individual-commits.html Así que me ramifiqué de A y escogió cuidadosamente D y F, luego fusionó el resultado en la rama original para actualizarlo. – Jake

+0

¿Realmente escogiste la F? Pensé que F era solo para invertir B y C, ¿entonces no tenía nada que hacer después de C '? – Gauthier

+0

Lo siento, ahora no estoy seguro. Quizás lo hice, pero realmente no era necesario. – Jake

Cuestiones relacionadas