2012-06-15 18 views
55

En un intento de lograr git nirvana, me paso el día aprendiendo cómo aprovechar rebase para situaciones en las que actualmente me uno.¿Cómo puedo usar git rebase sin requerir un empuje forzado?

Al ejecutar a través de lo que considero que es un flujo de git 101 (que deletreo a continuación), tengo que push --force al empujar mis cambios de nuevo al origen.

yo no soy el único - Yo sé que esto está cubierto de tierra (ver 1, 2, 3, 4, 5), y entiendo las razones técnicas por qué es necesaria una fuerza. Mi problema es este --- hay muchas (muchas) entradas de blog cantando los elogios de rebase y cómo ha cambiado sus vidas (ver 1, 2, 3, 4 para enumerar algunas), pero ninguno de ellos menciona que push --force es parte de su flujo. Sin embargo, casi todas las respuestas a las preguntas existentes sobre el stackoverflow dicen cosas como "sí, si vas a rebasear, tienes que usar push --force".

Dado el número y la religiosidad de los defensores de rebase, Tengo que creer que usar 'push --force' no es una parte inherente de un flujo de rebase, y que si uno a menudo tiene que forzar sus empujes, están haciendo algo mal.

push --force es un bad thing.

Así que aquí está mi flujo. ¿De qué manera podría lograr los mismos resultados sin una fuerza?

Ejemplo simple

dos ramas:

  • v1.0 - una rama de lanzamiento, incluye solamente parches
  • maestro - todo para la próxima versión.

Tengo algunas confirmaciones de parches y algunas confirmaciones para la próxima versión.

premerge

me gustaría incorporar los parches en mi maestro para que no están perdidos para la próxima versión. Pre-iluminación que había simplemente:

git checkout master 
git merge v1.0 

Pero ahora estoy tratando

git checkout master 
git rebase v1.0 

así que ahora estoy aquí:

enter image description here

Tiempo para:

git push 

Sin dados.

Respuesta

29

Rebasing es una gran herramienta, pero funciona mejor cuando la usas para crear fusiones rápidas para ramas de tema en master. Por ejemplo, es posible que rebase su sucursal Agregar nuevo widget de frente principal:

git checkout add-new-widget 
git rebase -i master 

antes de realizar una combinación de avance rápido de la rama en el maestro. Por ejemplo:

git checkout master 
git merge --ff-only add-new-widget 

La ventaja de esto es que su historia no tendrá un montón de fusión compleja cometa o conflictos de fusión, ya que todos los cambios se restablecen en la punta del maestro antes de la fusión. Un beneficio secundario es que ha sido actualizado, pero no tiene que usar git push --force porque no está arruinando el historial en la rama principal.

No es ciertamente el único caso de uso para rebase, o el único flujo de trabajo, pero es uno de los usos más sensatos que he visto. YMMV.

+2

Gracias CG, creo que "usarlo para crear fusiones de avance rápido" es la clave. No se aplica a mi caso anterior donde tengo dos ramas vivas: una rama de desarrollo y una rama de lanzamiento, pero parece aplicarse muy bien para ramas temáticas temporales que solo son necesarias por un período limitado de tiempo, y luego pueden ser borrado una vez que están fusionados. Gracias de nuevo. –

+1

Entiendo esto, pero la pregunta original permanece. Creo que la respuesta real es la dada por [@Fabien Quatravaux] (http://stackoverflow.com/questions/11058312/how-can-i-use-git-rebase-without-requiring-a-forced-push# 11137857) – IsmailS

+2

Bueno, todavía tendrías que presionar la rama 1.0, ¿no? Al menos, así es como las cosas tienden a resultar para mí todo el tiempo. El método de Fabiens evitaría que eso sucediera. – joerx

12

Tienes que forzar push si rebases, y ya has publicado tus cambios, ¿verdad?

Utilizo rebase un montón, pero o bien publico en algo privado donde no importa un empuje de fuerza (por ejemplo: mi propio clon en GitHub, como parte de una solicitud de extracción), o rebase antes de presionar para la primera vez.

Este es el corazón del flujo de trabajo en el que utiliza rebase, pero no fuerce demasiado el push: no publique cosas hasta que estén listas, no vuelva a establecer la base después de pulsar.

+0

Gracias Dan. ¿Podrías decirme cómo se debe lograr lo anterior, entonces? ¿No es este un escenario donde se aplica la rebase? –

+2

Si aisla todo su trabajo en ramas temáticas, configura un buen escenario para volver a basar.Usted 'rebase' los nuevos cambios realizados en su rama de tema, pero cuando haya completado los cambios de esa rama,' fusionará' la rama de nuevo en la rama de desarrollo principal. – redhotvengeance

+1

El problema es que ha publicado la rama, por lo que debe forzar la inserción en el repositorio. Debe renunciar a uno de los dos: publicar de la manera en que lo hace o cambiar el formato. Lo siento. –

20

@CodeGnome tiene razón. No debe volver a establecer la base maestra en la rama v1.0, sino la rama v1.0 en la maestra, eso hará toda la diferencia.

git checkout -b integrate_patches v1.0 
git rebase master 
git checkout master 
git merge integrate_patches 

Crear una nueva rama que apunta a v1.0, que se mueven nueva rama en la parte superior de la maestra y luego integrar la nueva versión de los parches V1.0 a la rama principal. Usted va a terminar con algo como:

o [master] [integrate_patches] Another patch on v1.0 
o A patch on v1.0 
o Another change for the next major release 
o Working on the next major release 
| o [v1.0] Another path on v1.0 
| o A patch on v1.0 
|/
o Time for the release 

Esta manera de utilizar rebase es recomendado por the official git documentation.

Creo que tiene razón acerca de git push --force: solo debe usarlo si cometió un error y empujó algo que no quería.

+0

Creo que esta es la mejor respuesta para el problema específico en el PO. Usted crea una bifurcación de fusión temporal y una rebase en eso, luego se fusiona con el maestro y se envía al origen. La rama temporal no tiene que ser empujada al origen. El único consejo adicional que daría es tener una rama de desarrollo o qa donde el código fusionado/rebasado pueda ser calificado. Después de la calificación, este código sería fusionado solo al maestro. Esto permite una fácil revisión si su proceso de calificación toma demasiado tiempo. Este es básicamente el proceso de "git flow". –

3

Creo que hay un buen caso de uso para este patrón de rebase-then-force-push que no es el resultado de un error: trabajar en una rama de características usted mismo desde múltiples ubicaciones (computadoras). Hago esto a menudo, ya que a veces trabajo en la oficina en mi escritorio, y algunas veces desde mi página de inicio/cliente en mi computadora portátil. Necesito rebase de vez en cuando para mantenerme al día con la rama principal y/o para hacer las fusiones más limpias, pero también necesito forzar el empuje cuando dejo una máquina para ir a trabajar en otra (donde simplemente la tiro). Funciona como un amuleto, siempre y cuando yo sea el único que trabaje en la sucursal.

+2

Tengo este mismo flujo de trabajo (trabajando desde múltiples computadoras/ubicaciones). Entonces, supongamos que estás trabajando en una rama de tema llamada 'miopica'. Siempre y cuando siempre refuerces una rama local desechable (que es simplemente una rama de mytopic) en "master" y luego la fusionas con la mítica, entonces nunca tendrás que forzar push. OP tiene un escenario ligeramente diferente, por lo que en un caso como ese podría ser necesario un empuje de fuerza. Sin embargo, creo que OP se está volviendo a cambiar por el camino equivocado, si lo hizo como lo describí, entonces no sería necesario empujar la fuerza. – bwv549

0

Esto es lo que yo uso (asumiendo que su nombre de la sucursal es foobar):

git checkout master    # switch to master 
git rebase foobar    # rebase with branch 
git merge -s ours origin/master # do a basic merge -- but this should be empty 
git push origin master   # aaand this should work 
+1

El maestro de rebase se ve raro. –

+0

'git' no es sin personalidad – redolent