2011-01-19 20 views
12

En la fusión de mis cambios contra un maestro de aguas arriba, que con frecuencia se encuentran a mí mismo haciendo lo siguiente:sobrescritura y empujando una rama Git

git checkout somefeature 
git checkout -b integration 
git rebase master # resolving conflicts along the way 
git checkout somefeature 
git merge integration # or rebase, doesn't matter in this example 

a menudo a encontrar que la fusión de la rama de integración de nuevo en mi rama de la característica no hacer a algunos conflictos. La primera pregunta que tengo es, "¿por qué sucede esto si mi rama de integración es descendiente de alguna característica y ya resolví conflictos contra el maestro de nivel superior?"

Si se pregunta por qué estoy usando una rama de integración para empezar, es para evitar contaminar mi rama actual con una fusión a medio fracasar.

Mi solución actual es hacer esto:

git checkout integration 
git branch -f somefeature # overwrite the branch 

El problema ahora es que no puedo empujar mis cambios de nuevo a una rama remota:

git push origin somefeature 
! [rejected]  somefeature -> somefeature (non-fast forward) 

Así que ahora tengo que quitar la rama remota y volver a presionar mis cambios. Esta no puede ser la forma óptima de hacerlo, así que me pregunto, "¿cuál es la mejor manera de sobrescribir una rama y enviar los cambios a una sucursal remota?"

Respuesta

15

El problema es causado porque git rebase genera una nueva serie de confirmaciones de que no descienden de la rama somefeature, a continuación, cuando intenta y unirlos de nuevo en la resolución de conflictos somefeature hecho durante el rebase no se aplica. Si tuviera que fusionar en lugar de rebase, esto funcionaría ya que la combinación de confluencia sería descender de la rama somefeature.

En términos de empujar a la rama remota, puede usar --force para hacer que la inserción tenga éxito, que causará problemas a cualquier otra persona que tenga una copia.

+3

Tenga en cuenta que nunca debe cambiar las confirmaciones ya publicadas, ya que otras personas que trabajan con usted se encontrarán con los mismos problemas que usted, que ya han duplicado las confirmaciones incompatibles en su repositorio. Reasignar está bien siempre y cuando sea solo local, pero volver a establecer las bases y volver a publicarlas es malo; de ahí el error * "rechazado" * de Git (es inteligente y advierte que probablemente estés haciendo algo mal). – poke

+0

Ah, estaba usando fusionar para la conveniencia de la resolución de conflictos paso a paso sin considerar que los commits no serían descendientes de la rama somefeature. Aceptar esto como la verdadera respuesta a mi pregunta. ¡Muchas gracias! – tmountain

0

Su primer bit de operaciones es muy extraño. Usted hace una copia de alguna característica. Usted rebase eso contra el maestro. Luego vuelves a esa función y la fusionas con el equivalente reescalado de sí mismo. Esta no es la manera de hacer las cosas.

No compliques demasiado las cosas. Si desea que la rama de características comience en otro lugar (como el último máster), simplemente vuelva a establecer una base.

Luego empújelo con --force (o -f). Dígale a alguien más que estaba usando esa rama de características que tienen que buscar los cambios y ajustar todo lo que tenían localmente que aún no hayan enviado.

Merge es mejor en el caso cuando otros han estado trabajando en ello.

Espero que esto ayude.

+1

Eh, estaba bajo la impresión de que se hace una copia de somefeature y luego la fusión que contra la maestra sería una manera fácil de combinar dos ramas sin curioseaba con cualquiera de los originales. Supongo que es mejor hacer una rebase estándar. Gracias. – tmountain

+0

puede fusionarlo en su lugar. Intentabas hacer ambas cosas. Ese fue el problema. Depende de usted si desea fusionar a maestro o rebase a maestro. Uno produce una historia lineal, el otro conserva el punto en el que se ramificó. Tu elección. Tendrá potencialmente más conflictos para resolver si toma la ruta de rebase además de "mover el queso de alguien" potencialmente. –

4

Puede usar git merge -s recursive -Xtheirs, que resolverá automáticamente los conflictos a favor de la rama de integración. Sin embargo, eso todavía se fusiona y puede que no funcione bien con los archivos que se mueven y cosas por el estilo.

Sin embargo, como su rama está presionada, tiene una razón para querer mantener su historial. Para obtener el comportamiento ideal que desea, puede usar la estrategia 'nuestra' en la rama de integración.

git checkout somefeature 
git checkout -b integration 
git rebase master # resolving conflicts along the way 
git merge -s ours somefeature # mark integration as superseding the somefeature branch 
git checkout somefeature 
git merge integration # this is now a fast-forward, no conflicts 
+0

Sin embargo, en general, la solución de Nemo157 es mejor: solo use merge en lugar de rebase desde el principio para las ramas de características que se publican en un repositorio no local. Así es como git está diseñado para funcionar. –

+0

No estaba al tanto de la estrategia de fusión 'nuestra'. Esta parece la solución que he estado buscando. ¡Gracias! – tmountain