Git falla al rebasar en confirmaciones modificadas

Usamos gerrit para revisar el código. Cuando trabajo con un problema mayor, a veces envío varios commits a Gerrit que dependen el uno del otro. Aquí hay una situación de este tipo, donde a, byc son commits que están esperando la revisión del código en Gerrit:

c | b | a | origin/master 

Si recibo un comentario sobre a, necesito solucionar cualquier problema que encuentre el revisor del código, y realizar nuevas confirmaciones para a, byc (Gerrit nunca puede manejar los conflictos que surgen cuando cambia la dependencia de b). Para arreglar esto, busco una nueva twig llamada cr_fix desde donde estoy trabajando (digamos master), y hago un reinicio de git –hard HEAD ^^ (o usando el id para commit a) así que termino con esto :

 a | origin/master 

Ahora puedo solucionar los problemas informados en a, hacer una nueva confirmación y enviarla a Gerrit. Ahora vuelvo a dominar y hacer

 git rebase cr_fix 

La intención es replace el commit a en master con el commit a en cr_fix.

Esta estrategia funciona para mí, pero está plagada de git que registra constantemente conflictos de fusión, no parece ser capaz de resolver las cosas más simples.

Lo más notable es que el primer commit que maneja en el command de rebase final (a en cr_fix en la parte superior de un master) entra en conflicto prácticamente en todas partes donde se realizó un cambio en cr_fix.

He aprendido a estas alturas que básicamente siempre puedo comenzar la rebase con un git rebase –skip, pero estoy nervioso de que haga esto y pierda un commit en alguna parte.

Entonces, ¿hay alguna forma en que pueda modificar mi flujo de trabajo para no tener que lidiar con estos conflictos constantes al rebasar? Tal vez alguna opción que pueda usar o configurar?

Sus problemas provienen de tratar de rebase A en la parte superior de A '(usando mayúsculas aquí para legibilidad). Lo que realmente quieres hacer es reubicar B y C en la parte superior de A ', creando B' y C '. La forma más fácil de hacerlo es usar una rebase interactiva,

 git rebase -i origin/master 

y modificar A en A ', y Git colocará automáticamente B y C en la parte superior. Por supuesto, esto puede causar conflictos, pero si A 'toca exactamente el mismo código que B o C, eso es inevitable.

Si insistes en crear una nueva sucursal para arreglar A en A ', eso está bien también (aunque creo que estás trabajando innecesariamente duro) pero debes asegurarte de que no estás tratando de aplicar A.

Cuando corres

 git rebase cr_fix 

de hecho estás diciendo "retroceder la twig actual hasta que encuentres una confirmación que sea alcanzable desde cr_fix y rebase esos commits a cr_fix". Dada la situación en la que te encuentras,

  o----A----B----C ^ \ | ------------A' | ^ origin/master | cr_fix 

estarás modificando A, B y C en la parte superior de A '. Para asegurarte de que solo estás modificando B y C, utiliza git rebase --onto :

 git rebase --onto A' A 

Esto significa "retroceder hasta llegar a una confirmación accesible desde A y volver a establecer esas confirmaciones en A '".

Si se trata del mismo conflicto una y otra vez, puede usar rerere (consulte la documentation oficial en http://git-scm.com/blog/2010/03/08/rerere.html )

Sin embargo, no lo recomendaría, porque tendrás que revertirlo manualmente si cometes un error al resolver el conflicto.

Si entiendo tu problema correctamente, estás tratando de volver a establecer la base de tu twig original en tu nuevo cambio.

Personalmente, nunca uso Rebase junto con Gerrit ya que siempre crea conflictos de fusión. Después de la fijación de commit, su tree se ve así:

 origin/master --- a' \---a--b--c ^ | cr_fix 

Ahora hacer una rebase de cr_fix on a' muy a menudo crea un conflicto ya que a gran parte de los cambios en a también están presentes en a' . Deberías simplemente elegir b y c y no deberías tener ningún conflicto y tu tree debería verse así:

 origin/master --- a'--b'--c' \---a--b--c ^ | cr_fix 

Al usar Gerrit, nunca es mejor utilizar git pull y git rebase debido a la estructura de tree cambiante como resultado de las revisiones de código que normalmente no verías en otros repositorys de git.


@Magnus

No uso rebase porque:

  1. Yo uso TortoiseGit, tal vez tiene la opción de git rebase --onto , pero para ser honesto, no sabía que pudieras hacer esto de todos modos
  2. Cuando rebase, el original se ha ido. Si surge algún conflicto en la database y cometió un error al solucionarlo, perdió su código original. Al usar cherry-pick siempre podrá hacer reference a la revisión original
  3. Como un git newby relativo, tengo que mostrarle a los principiantes de git total cómo solucionar problemas con sets de cambios desactualizados, etc. El uso de rebase es muy delicado y, a menudo, lleva al código de pérdida. Lo mejor es dejar que siempre usen cherry-pick , después de un cherry-pick , siempre puedes reiniciar el HEAD y volver a intentarlo. Si arruinas una rebase has perdido tu set de cambios original. Y sí, sé que puedes recuperarlo si conoces el SHA1 , pero puedes ahorrarte el problema usando cherry-pick

Espero que entiendas por qué prefiero y recomiendo usar cherry-pick sobre rebase .