Estoy usando git en un nuevo proyecto que tiene dos ramas de desarrollo paralelas, pero actualmente experimentales:
master
: importación de la base de código existente más unas cuantas modificaciones de las que generalmente estoy seguroexp1
: rama experimental #1exp2
: rama experimental #2exp1
y exp2
representan dos enfoques arquitectónicos muy diferentes. Hasta que no avance no tengo forma de saber cuál de ellos (si es que alguno) funcionará. A medida que avanzo en una rama, a veces tengo ediciones que serían útiles en la otra rama y me gustaría fusionarlas.
**¿Cuál es la mejor manera de fusionar cambios selectivos de una rama de desarrollo a otra dejando todo lo demás?
Enfoques que he considerado:
git merge --no-commit
seguido de la eliminación manual de un gran número de ediciones que no quiero que sean comunes entre las ramas.git checkout
para pasar a la otra rama y luego más copias manuales del directorio temporal al árbol de trabajo.Una variación de lo anterior. Abandonar las ramas exp
por ahora y utilizar dos repositorios locales adicionales para la experimentación. Esto hace que la copia manual de archivos sea mucho más sencilla.
Los tres enfoques parecen tediosos y propensos a errores. Espero que haya un enfoque mejor; algo parecido a un parámetro de ruta de filtrado que haga que git-merge
sea más selectivo.
Se utiliza el comando cherry-pick para obtener commits individuales de una rama.
Si los cambios que quieres no están en commits individuales, entonces usa el método mostrado aquí para dividir el commit en commits individuales. A grandes rasgos, se utiliza git rebase -i
para obtener el commit original a editar, luego git reset HEAD^
para revertir selectivamente los cambios, y luego git commit
para confirmar ese bit como un nuevo commit en el historial.
Hay otro buen método aquí en Red Hat Magazine, donde usan git add --patch
o posiblemente git add --interactive
que te permite añadir sólo partes de un trozo, si quieres dividir diferentes cambios en un archivo individual (busca en esa página "split").
Habiendo dividido los cambios, ahora puedes escoger sólo los que quieras.
No me gustan los enfoques anteriores. El uso de cherry-pick es genial para escoger un solo cambio, pero es un dolor si quieres traer todos los cambios excepto algunos malos. Este es mi enfoque.
No hay ningún argumento --interactivo
que puedas pasar a git merge.
Esta es la alternativa:
Tienes algunos cambios en la rama 'feature' y quieres llevar algunos, pero no todos, a 'master' de una manera no descuidada (es decir, no quieres seleccionar y confirmar cada uno)
git checkout feature
git checkout -b temp
git rebase -i master
# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change
# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
git checkout master
git pull . temp
git branch -d temp
Así que simplemente envuelva esto en un script de shell, cambie master en $to y cambie feature en $from y estará listo:
#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp
La respuesta de 1800 INFORMATION es completamente correcta. Sin embargo, como soy un novato en git, "utilizar git cherry-pick" no fue suficiente para mí para resolver esto sin un poco más de investigación en Internet, así que pensé en publicar una guía más detallada en caso de que alguien más esté en un barco similar.
Mi caso de uso era querer tirar selectivamente los cambios de la rama de github de otra persona en mi propia. Si usted ya tiene una rama local con los cambios que sólo tiene que hacer los pasos 2 y 5-7.
Crea (si no está creada) una rama local con los cambios que quieres traer.
$ git branch mybranch <rama base>
.
Cambia a ella.
$ git checkout mi rama
Baja los cambios que quieras de la cuenta de la otra persona. Si aún no lo has hecho, querrás añadirlos como remotos.
$ git remote add repos-w-changes <git url>
Baja todo lo que haya en su rama.
$ git pull repos-w-changes branch-i-want
.
Vea los registros de commit para ver qué cambios quiere:
$ git log
.
Vuelve a la rama en la que quieres introducir los cambios.
$ git checkout originalbranch
Selecciona tus commits, uno por uno, con los hashes.
$ git cherry-pick -x hash-de-commit
Sugerencia: http://www.sourcemage.org/Git_Guide