2012-03-01 9 views
7

Uso de git v1.7.1 Estoy tratando de hacer una rebase con las características --preserve-merges y --onto al mismo tiempo. Los resultados finales parecen sin compromisos de fusión, por lo que parecen lineales. Prefiero preservar las asignaciones de fusión, por la misma razón que la gente a menudo usaría --preserve-merges (más fácil ver el grupo de confirmaciones que lógicamente era una función separada y desarrollada en su propia rama).git rebase "--preserve-merges --onto" no conserva las fusiones

Mi rama principal (el destino para el rebase) es aburrido:

A-B-C

La rama de la característica que quiero tomar de una rama tiene sub-característica que se ha fusionado en él. Como:

 X - Y 
/ \ 
V-W ------ Z 

donde z es una combinación de cometer que es la cabeza de la rama de la característica para tomar de, y X e Y eran en una rama sub-característica.

que estoy usando: git rebase --preserve-merges --onto C V Z

Me gustaría terminar con:

  X - Y 
     / \ 
A-B-C-W ------ Z 

Pero en vez estoy recibiendo:

A-B-C-W-X-Y 

Desde Z era un conflictivo fusión gratuita, el estado final del código es correcto, pero la historia no es tan expresiva como me gustaría.

¿Hay alguna manera de obtener lo que quiero?

corregir a la dirección @Bombe: Escribí un script bash para construir mi ejemplo. En mi sistema (RHEL 6.2 con git 1.7.1) esto demuestra mi problema.

#! /bin/bash 
# start a new empty repo 
git init 
# make some commits on the master branch 
git checkout master 
touch A.txt; git add A.txt; git commit -m "add A.txt"; git tag Atag 
touch B.txt; git add B.txt; git commit -m "add B.txt"; git tag Btag 
touch C.txt; git add C.txt; git commit -m "add C.txt"; git tag Ctag 
# now build the feature branch 
# start at Btag (more or less arbitrary; point is it's before C) 
git checkout Btag 
git checkout -b feature 
touch V.txt; git add V.txt; git commit -m "add V.txt"; git tag Vtag 
touch W.txt; git add W.txt; git commit -m "add W.txt"; git tag Wtag 
# now a subfeature 
git checkout -b subfeature 
touch X.txt; git add X.txt; git commit -m "add X.txt"; git tag Xtag 
touch Y.txt; git add Y.txt; git commit -m "add Y.txt"; git tag Ytag 
# merge the subfeature into the feature 
# preserves branch history with --no-ff 
git checkout feature 
git merge --no-ff subfeature 
# the merge commit is our Z 
git tag Ztag 
# one more commit so that merge isn't the tip (for better illustration of Z missing later) 
touch postZ.txt; git add postZ.txt; git commit -m "add postZ.txt"; git tag postZtag 
# now do the rebase 
git rebase --preserve-merges --onto Ctag Vtag 
# optionally move the master branch forward to the top of feature branch 
git checkout master 
git merge feature 

Antes de que el rebase me sale:

 X-Y 
    / \ 
    V-W-----Z-postZ 
/
A-B-C 

Después de que el rebase me sale:

 X-Y 
    / \ 
    V-W-----Z-postZ 
/
A-B-C-W'-X'-Y'-postZ' 

nota la falta de Z 'entre Y' y postZ'.

Respuesta

10

Muchas gracias a Bombe y a un amigo fuera de línea por señalar que funciona para algunas personas. Con esa inspiración, ahora soy capaz de responder mi propia pregunta.

Respuesta corta: las versiones de git anteriores a 1.7.5.2 mostrarán este mal comportamiento.

Respuesta larga: en el repositorio de origen propio de git, commit c192f9c865dbdae48c0400d717581d34cd315fb8 el 28 de abril de 2011 fue explícitamente una solución para este problema.

citar el mensaje de confirmación (por Andrew Wong):

git-rebase--interactive.sh: preserve-merges fails on merges created with no-ff 

'git rebase' uses 'git merge' to preserve merges (-p). This preserves 
the original merge commit correctly, except when the original merge 
commit was created by 'git merge --no-ff'. In this case, 'git rebase' 
will fail to preserve the merge, because during 'git rebase', 'git 
merge' will simply fast-forward and skip the commit. For example: 

       B 
      /\ 
      A---M 
      /
    ---o---O---P---Q 

If we try to rebase M onto P, we lose the merge commit and this happens: 

       A---B 
       /
    ---o---O---P---Q 

To correct this, we simply do a "no fast-forward" on all merge commits 
when rebasing. Since by the time we decided to do a 'git merge' inside 
'git rebase', it means there was a merge originally, so 'git merge' 
should always create a merge commit regardless of what the merge 
branches look like. This way, when rebase M onto P from the above 
example, we get: 

        B 
       /\ 
       A---M 
       /
    ---o---O---P---Q 

Solución: Cambiar de versión de Git, la construcción de la fuente si es necesario.

Btw, utilicé git bisect para resolver esto. Herramienta impresionante

0

Acabo de tratar de recrear su situación, y puedo informar que --preserve-merges parece estar funcionando como se anuncia. Cuando estás en comprometerse Z, solo tema:

git rebase --preserve-merges --onto C V 

Eso es lo que hice y preservó la fusión cometió.

+0

He editado la publicación original para proporcionar los pasos para reproducir mi problema. Estoy seguro de que tienes razón, pero no veo lo que estoy haciendo mal. – RaveTheTadpole

+2

Y de hecho tengo una versión más grande que 1.7.5.2. :) – Bombe

1

Me encontré con este problema. Tenga en cuenta mi versión de Git, es 1.7.10.2.

Estoy haciendo una rebase de un rango de compromiso (identificado por sus hashes SHA1) en una rama y también carece de la última confluencia de fusión.

Mi solución fue reubicar W a X en C (sin --preserve-merges) y luego rebase (con --preserve-merges) Y, Z y postZ en X '.

Espero que esto ayude.