2009-11-12 36 views
6

Déjame explicar el problema en detalle.¿Cómo fusionar una rama a otra rama en GIT?

Tengo una rama principal de git en la que creé una nueva rama lateral bug10101010, ahora quiero fusionar la bug10101010 a main. Hasta ahora todo está bien. Ahora tengo una rama diferente del mismo producto, llamada Legacy. Quiero fusionar el bug10101010 con la rama heredada en GIT.

¿Alguna idea?

No puedo simplemente fusionarlo directamente, ya que la rama bug10101010 se deriva de la rama principal y en el legado solo necesito la diferencia entre la rama bug10101010 y su rama padre.

+0

@Priyank: Estoy de acuerdo, el parche es más simple. Pero el método que describo no es complejo. También ilustra la facilidad con la que puedes clonar un repositorio y realizar cualquier operación de Git que desees, siempre que no estés presionando desde allí. – VonC

Respuesta

2

Esto es difícil de hacer. Git guarda el historial de fusión, y si "cherrypick" apunta a una confirmación en bug10101010 como padre (lo que indica que ha realizado una combinación), Git asumirá que todas las confirmaciones anteriores (hasta el punto en que se dividieron) se combinaron como bien. Te da problemas cuando quieres hacer una fusión "real".

Por otro lado, puede generar manualmente un parche a partir de esa (y solo esa) confirmación específica. Pero eso también le dará problemas cuando más tarde realice la combinación "real", ya que intenta aplicar su confirmación manejada manualmente dos veces.

Pero, una vez más, dado que una rama se llama "Legacy", sospecho que no planea hacer esa combinación real de todos modos, en cuyo caso es muy libre de hacerlo de todos modos.

Aquí hay interesting blog post on the topic.

+0

Gracias por el maravilloso enlace. Entonces, ¿cuál es su recomendación y cómo hacer lo anterior? O permítanme reformular la pregunta: Necesito la capacidad de crear transacciones específicas de errores que siempre se combinan con main, pero necesita la capacidad de reproducir estas transacciones en otras sucursales a voluntad. –

+0

¿Qué quiere decir con "siempre fusionado con main"? Una rama de error específica solo debería fusionarse de nuevo a la rama principal una vez. Si mi respuesta general, junto con el enlace del blog y la documentación general de git, no te llevan a ningún lado, podrías considerar actualizar tu pregunta original que detalla el flujo de trabajo específico que buscas un poco más. Quizás pueda ayudar entonces. – Mizipzor

+0

Las preguntas son las mismas, la bifurcación bug10101010 se fusiona con la principal, ya que todas las correcciones de errores deben estar presentes en la rama principal. Pero, ¿cómo fusionaría los cambios específicos en el hecho en la rama bug10101010 con respecto a su padre a la rama heredada? Como está sugiriendo generar manualmente un parche y aplicarlo, pero al hacerlo estoy perdiendo la capacidad de rastrear que estos cambios provienen de esta rama. –

1

Use git-diff y luego git-apply?

+0

cómo harías un seguimiento entonces, que lo que fusionaste provino de la bifurcación bug10101010, que básicamente es solo una transacción. También no es sencillo. Necesito la capacidad de especificar solo el nombre de la sucursal y fusionar los cambios. –

+0

La idea también es crear una transacción de errores (usando ramas pequeñas) y reproducir esas transacciones, sin esfuerzo a cualquier parte (cualquier rama). Crear un parche y fusionar el mismo, se puede hacer en CVS/SVN también, entonces no se usa mover a Git. –

+0

Si la bifurcación es una transacción, una vez finalizado su propósito, la sucursal se debe eliminar de manera efectiva, y por lo tanto, basta con registrar que el parche es una solución para bugXXXXXXXXX. Dado que el punto de la transacción es encapsular los cambios, ¿la suma total de los cuales se puede rastrear como un agregado? – Amber

6

Debe usar git rebase --onto aquí y especifique un rango.
(ver git rebase man page:

trasplante de una rama tema basa en una rama a otra, para pretender que la rama bifurcada tema de esta última rama, usando rebase --onto

.).

Por supuesto, esto movería su rama bug10 en la parte superior de la rama legacy, que no es lo que quiere/necesita.

lo tanto, una solución sería hacer que rebase en un acuerdo de recompra clonado, luego la fusiona 'mejorada' legacy rama (el que está en el repositorio clon, con los bug10 modificaciones en la parte superior de la misma) a lo local y la rama legacy actual (la que desea modificar, dejando bug10 solo).

Ahora:

  • esto implica una cesión temporal adicional (que puede conducir a la limitación de espacio en disco)
  • todo en todos, esto es bastante equivalentes para definir un parche y aplicarlo a legacy rama, por lo que la otras respuestas (parche) son válidas (y más simples).
  • la única ventaja que veo en este método es la oportunidad de definir un entorno heredado en el que rebase lo que desea (como las confirmaciones bug10), antes de enviar solo esa rama legacy a su repositorio original (no presionaría bug10, ya que su historia habría sido completamente reescrita!)

Solo quería ver si funciona, así que ... Pongamos a prueba ese enfoque.
(Git1.6.5.1, en un viejo XP SP2, con una sesión de PowerShell 1.0 debido a la Start-Transcript command)


PS D:\> mkdir git 
PS D:\> cd git 
PS D:\git> mkdir tests 
PS D:\git> cd tests 
PS D:\git\tests> git init mainRepo 

me gusta la forma en que no tengo más para hacer el directorio git repo primero, ¡entonces escríbalo git init! Since 1.6.5:

"git init" aprendieron a mkdir/chdir en un directorio cuando se le da un argumento extra (es decir, "git init this").

¡Esto es GENIAL!

Creemos 3 archivos, para 3 propósitos diferentes.
(Por el bien de ejemplo, voy a mantener el archivo de modificaciones separan por sucursal: ningún conflicto durante la fusión o rebase aquí.)

PS D:\git\tests> cd mainRepo 
PS D:\git\tests\mainRepo> echo mainFile > mainFile.txt 
PS D:\git\tests\mainRepo> echo contentToBeFixed > toBeFixedFile.txt 
PS D:\git\tests\mainRepo> echo legacyContent > legacy.txt 
PS D:\git\tests\mainRepo> git add -A 
PS D:\git\tests\mainRepo> git ci -m "first commit" 
PS D:\git\tests\mainRepo> echo firstMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "first evol, for making 1.0" 
PS D:\git\tests\mainRepo> git tag -m "1.0 legacy content" 1.0 

En este punto, un git log --graph --oneline --branches rendimientos:

* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

vamos a construir una rama legacy

PS D:\git\tests\mainRepo> git co -b legacy 
PS D:\git\tests\mainRepo> echo aFirstLegacyEvol >> legacy.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a first legacy evolution" 

volvemos al maestro, haga otra confirmación, que vamos a etiquetar " 2.0" (! Un comunicado de que se necesita un poco de corrección de errores)

PS D:\git\tests\mainRepo> git co -b master 
PS D:\git\tests\mainRepo> git co master 
PS D:\git\tests\mainRepo> echo aMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a main evol" 
PS D:\git\tests\mainRepo> echo aSecondMainEvolFor2.0 >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a second evol for 2.0" 
PS D:\git\tests\mainRepo> git tag -m "main 2.0 before bugfix" 2.0 

Tenemos:

* e727105 a second evol for 2.0 
* 473d44e a main evol 
| * dbcc7aa a first legacy evolution 
|/ 
* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

Ahora hacemos un bug10 corrección de errores rama:

PS D:\git\tests\mainRepo> git co -b bug10 
PS D:\git\tests\mainRepo> echo aFirstBug10Fix >> toBeFixedFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a first bug10 fix" 
PS D:\git\tests\mainRepo> echo aSecondBug10Fix >> toBeFixedFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "a second bug10 fix" 

Añadamos una confirmación final en la rama principal

PS D:\git\tests\mainRepo> git co master 
PS D:\git\tests\mainRepo> echo anotherMainEvol >> mainFile.txt 
PS D:\git\tests\mainRepo> git ci -a -m "another main evol" 

Estado final de nuestro repositorio principal:

* 55aac85 another main evol 
| * 47e6ee1 a second bug10 fix 
| * 8183707 a first bug10 fix 
|/ 
* e727105 a second evol for 2.0 
* 473d44e a main evol 
| * dbcc7aa a first legacy evolution 
|/ 
* b68c1f5 first evol, for making 1.0 
* 93f9f7c first commit 

En esta etapa, no hará ninguna manipulación adicional en mainRepo. Solo lo clonaré para hacer algunas pruebas. Si eso falla, siempre puedo volver a este repositorio y clonarlo nuevamente.

El primer clon en realidad es obligatoria, con el fin de llevar a cabo nuestra git rebase --onto

PS D:\git\tests\mainRepo> cd .. 
PS D:\git\tests> git clone mainRepo rebaseRepo 
PS D:\git\tests> cd rebaseRepo 

Necesitamos dos de las ramas mainRepo en nuestro repositorio clonado:

PS D:\git\tests\rebaseRepo> git co -b bug10 origin/bug10 
PS D:\git\tests\rebaseRepo> git co -b legacy origin/legacy 

Vamos rebase solamente bug10 (que es todo confirma después de 2.0 etiqueta hasta HEAD de bug10 rama):

PS D:\git\tests\rebaseRepo> git co bug10 
PS D:\git\tests\rebaseRepo> git rebase --onto legacy 2.0 
First, rewinding head to replay your work on top of it... 
Applying: a first bug10 fix 
Applying: a second bug10 fix 

En este punto bug10 se ha repetido en la parte superior de legacysin todos los demás realiza poco.
Ahora podemos avanzar rápidamente HEAD de legacy a la parte superior de la rama bug10 reproducida.

PS D:\git\tests\rebaseRepo> git co legacy 
Switched to branch 'legacy' 
PS D:\git\tests\rebaseRepo> git merge bug10 
Updating dbcc7aa..cf02bfc 
Fast forward 
toBeFixedFile.txt | Bin 38 -> 104 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 

El contenido sigue lo que necesitamos:

  • Tenemos todo el contenido antiguo:

 

PS D:\git\tests\rebaseRepo> type legacy.txt 
legacyContent 
aFirstLegacyEvol 

 

  • el contenido de la rama main es no sólo hasta 1.0 etiqueta (raíz para legacy rama), y no más lejos.

 

PS D:\git\tests\rebaseRepo> type mainFile.txt 
mainFile 
firstMainEvol 

 

  • y las correcciones son bug10 aquí:

 

PS D:\git\tests\rebaseRepo> type toBeFixedFile.txt 
contentToBeFixed 
aFirstBug10Fix 
aSecondBug10Fix 

 

Eso es todo.
La idea es lograr eso 'mejorada' legacy sucursal en tu repositorio original, que todavía tendrá su bug10 sin cambios (es decir, aún partiendo de la etiqueta 2.0, y no reproducidos en cualquier lugar como lo hicimos en el rebaseRepo.
En este repo clonado, sigo la rama origin/legacy, para unirme a él la rama legacy de otra fuente remota: rebaseRepo.

PS D:\git\tests\rebaseRepo> cd .. 
PS D:\git\tests> git clone mainRepo finalRepo 
PS D:\git\tests> cd finalRepo 

PS D:\git\tests\finalRepo> git co -b legacy origin/legacy 

En este repo originales (que sólo se clonó a no meterse con el estado de la mainRepo, en caso de que tuviera algunos otros experimentos a realizar), Anunciaré rebaseRepo como un control remoto, a buscar sus ramas.

PS D:\git\tests\finalRepo> git remote add rebasedRepo D:/git/tests/rebaseRepo 
PS D:\git\tests\finalRepo> type D:\git\tests\finalRepo\.git\config 
[remote "origin"] 
    fetch = +refs/heads/*:refs/remotes/origin/* 
    url = D:/git/tests/mainRepo 
[branch "master"] 
    remote = origin 
    merge = refs/heads/master 
[branch "legacy"] 
    remote = origin 
    merge = refs/heads/legacy 
[remote "rebasedRepo"] 
    url = D:/git/tests/rebaseRepo 
    fetch = +refs/heads/*:refs/remotes/rebasedRepo/* 

PS D:\git\tests\finalRepo> git fetch rebasedRepo 
remote: Counting objects: 8, done. 
remote: Compressing objects: 100% (6/6), done. 
remote: Total 6 (delta 3), reused 0 (delta 0) 
Unpacking objects: 100% (6/6), done. 
From D:/git/tests/rebaseRepo 
* [new branch]  bug10  -> rebasedRepo/bug10 
* [new branch]  legacy  -> rebasedRepo/legacy 
* [new branch]  master  -> rebasedRepo/master 

Ahora podemos actualizar legacy sin tocar a bug10:

PS D:\git\tests\finalRepo> git merge rebasedRepo/legacy 
Updating dbcc7aa..4919b68 
Fast forward 
toBeFixedFile.txt | Bin 38 -> 104 bytes 
1 files changed, 0 insertions(+), 0 deletions(-) 

puede repetir el proceso tantas veces como desee, siempre nuevas bug10 compromete necesitan ser reproducido en la parte superior de un viejo legacy rama, sin incluir todas las confirmaciones intermedias.

+0

Debo decir ¡WoW !, pero estoy casi confundido con los pasos y parece tan complejo para un novato como yo. Solo uso el parche manual. git diff label label ~ y luego git apply, eso me parece fácil. –

+0

Al final de esto, la rama principal no tiene los cambios de error10, ¿verdad?Pensé que lo que el poster original (y yo) queríamos era tener bug10 tanto en el legado como en la rama principal. – huggie

+0

@huggie, el OP mencionó "I wan't", que, hace más de cuatro años, debo haber interpretado de manera diferente. – VonC

Cuestiones relacionadas