2010-01-08 11 views
15

Esta es la situación. Estoy trabajando en la rama master. Creo file1 y commit. Creo file2 y commit. Whoops. Es posible que desee utilizar el archivo2, algún día, pero definitivamente no es algo que deba incluirse en la rama principal. Para no perder el archivo2 utilizogit: ¿Cómo sobrescribo todos los cambios locales en la fusión?

git checkout head~1 
git branch new-branch 
git checkout new-branch 

para poder seguir desarrollando. Agrego el archivo3 al new-branch. Si usted ha estado prestando atención, Tengo dos ramas, master que contiene "archivo1" y "archivo2" y new-branch que contiene "archivo1" y "archivo3".

Ahora es el momento de obtener los cambios que he hecho de nuevo en la rama principal. ¿Cuál es la mejor manera de hacer esto? Definitivamente quiero la cabeza de la rama master a señalar en los archivos que aparecen en new-branch, pero también no quiero perder el trabajo que he hecho en fichero2 al hacer un reset, en caso de que quiera usarlo.

Tenga en cuenta que esto es una simplificación. En lugar de solo tres archivos, tengo una docena de archivos con decenas de líneas de código que se cambian por todas partes con múltiples confirmaciones. Ciertamente espero que la solución no sea hacer una fusión/extracción de archivo por archivo, porque eso sería un gran dolor.

¿Alguna idea?

+0

Dijiste "Esto parece justo lo que necesito", pero ¿trataste de cambiar de rama como indiqué en mi respuesta? – VonC

+0

Lo hice. La respuesta de Randal fue aún más cercana a mi solución. Resulta que la clave es 'git reset --hard HEAD ~ 1'. No me di cuenta de que podías restablecer una cadena de confirmaciones con un comando. Todo lo que necesito hacer es ramificarme de la rama maestra actual, luego reiniciar de nuevo a donde comencé a equivocarme. – kubi

Respuesta

3

estoy trabajando en la rama principal. I crea el archivo1 y confirma.

date >file1 
git add file1 
git commit -m 'added file1' 

puedo crear fichero2 y comprometerse.

date >file2 
git add file2 
git commit -m 'added file2' 

chillidos. Es posible que desee utilizar el archivo2, algún día, pero definitivamente no es algo que debe colocarse en la rama principal .

Oops. Muy simple. Hacer una nueva rama de donde está:

git checkout -b savingfile2 

Esto hará que el fichero2 cambiar la confirmación de savingfile2. Ahora vuelve y descansar un paso en el maestro

git checkout master 
git reset --hard HEAD~1 

En este punto, las confirmaciones previas a maestro reflejarán la adición de archivo1, y cometer el adicional entre el maestro y savingfile2 será la adición de fichero2 a ese .

Si realizar más cambios en maestro, y luego quiere traer de vuelta fichero2 finalmente, tendrá que cambiar la base de que rama lateral en el nuevo maestro:

date >file3 
git add file3 
git commit -m 'adding file3' 
date >file4 
git add file4 
git commit -m 'adding file4' 

Y ahora por fin quiere fichero2:

git checkout savingfile2 
git rebase master # might need to fix conflicts here 
git checkout master 
git merge savingfile2 # will be a fast-forward 
git branch -d savingfile2 # no need any more 

Eso debería hacerlo.

+0

"git merge savingfile2 # será un avance rápido" <- ¿Qué tal si agregamos '--ff-only' para asegurarnos de ello? – weakish

+0

@weakish: esa opción es más nueva que la respuesta. :) –

1

Lo que debe hacer es lo que debería haber hecho cuando notado que su error de cometer fichero2: Deshacer el envío de datos (en lugar de crear una nueva rama):

git checkout master 
git reset HEAD^ 

Esto deja fichero2 sin seguimiento y sin daño alguno y posible modificaciones sin compromiso. Entonces usted debe (n) stash (ed) las modificaciones uncommited en caso de que quiera utilizarlos más adelante:

git stash save "modifications that should not be in the master branch" 

stashing se deshace de cualquier cambio local, lo que permite master que se hará en el punto de new-branch:

git merge new-branch 

El objetivo aquí fue eliminar la divergencia entre las dos ramas, es decir, hacer que master sea un antecesor de new-branch. De esta manera no hay fusión real tendría que ocurrir, y el último comando se acaba de avance rápido la rama master (siempre que no haya cambios locales).

+0

¿Cómo funcionaría si hubiera realizado varias confirmaciones en mi rama principal antes de notarlo? 'git reset' simplemente rebobinará HEAD, no me permitirá mover esos commits incorrectos, ¿verdad? – kubi

+0

Puede usar (interactivo) 'rebase' para descartar confirmaciones arbitrarias a lo largo del historial de confirmaciones (en oposición a' git reset') siempre que esas confirmaciones no se hayan enviado a ninguna parte. –

1

Dado que usted no siguió el optimal workflow descrito por Tomi Kyöstilä, sino también porque no publicó (empujó) nada todavía, ¿por qué no cambiar las dos ramas?
(siempre todo está comprometido)

master y new-branch son sólo algunos punteros a algunos SHA1:

$ git checkout master    #start from master 
$ git branch tmp     # tmp points on master HEAD 
$ git checkout new-branch   # switch to new-branch 
$ git branch -f master new_branch # master points at new-branch HEAD 
$ git checkout tmp     # switch back to *former* master branch 
$ git branch -f new_branch tmp  # new-branch points at former master HEAD 
$ git checkout master    # go to new master 
$ git branch -D tmp    # remove tmp pointer 

... y ya está.
(disclaimer: no determinado todavía, a fin de tratar con precaución;))

Ver:

+0

Esto parece justo lo que necesito. ¡Gracias! – kubi

Cuestiones relacionadas