Cómo fusionar archivos específicos de ramas Git


179

Tengo 2 ramas git branch1 y branch2 y quiero fusionar file.py en branch2 en file.py en branch1 y solo ese archivo.

En esencia, solo quiero trabajar en file.py en branch1 pero quiero aprovechar el comando merge. ¿Cuál es la mejor manera de hacer esto?



Respuestas:


207

Cuando el contenido es de file.pydesde BRANCH2 que ya no se aplica a BRANCH1 , se requiere recoger algunos cambios y dejando a los demás. Para un control total, haga una fusión interactiva con el --patchinterruptor:

$ git checkout --patch branch2 file.py

La sección de modo interactivo en la página de manual git-add(1)explica las teclas que se utilizarán:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

El comando dividir es particularmente útil.


3
¿Cómo podemos usar el parche y al mismo tiempo usar una herramienta de fusión? en lugar de las cosas clave
Gabriel

@Gabriel He usado Git incluso con archivos de parche y tarballs porque es muy fácil crear un repositorio ( git init <dir>) y finalmente tirarlo ( rm -r <dir>).
pdp

105

Aunque no es una fusión per se, a veces se necesita todo el contenido de otro archivo en otra rama. La publicación de blog de Jason Rudolph proporciona una manera simple de copiar archivos de una rama a otra. Aplique la técnica de la siguiente manera:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Ahora file.pyestá ahora en branch1 .


9191
Fácil, pero eso no es realmente una fusión . Simplemente se sobrescribe file.pycon lo que sea que esté en la rama 2.
Greg Hewgill

¿Qué sucede si fusiona el archivo de branch1 a branch2? ¡Tendrás conflicto!
Amir

¿Esto retiene el historial de compromiso?
C2H50H

18

Ninguna de las otras respuestas actuales "fusionará" los archivos, como si estuviera utilizando el comando de combinación. (En el mejor de los casos, requerirán que elija manualmente las diferencias). Si realmente desea aprovechar la fusión utilizando la información de un antepasado común, puede seguir un procedimiento basado en uno que se encuentra en la sección "Fusión avanzada" del git Manual de referencia.

Para este protocolo, supongo que desea fusionar el archivo 'ruta / a / archivo.txt' desde origen / maestro en CABEZA - modifique según corresponda. (No tiene que estar en el directorio superior de su repositorio, pero ayuda).

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-file debe usar todas las configuraciones de fusión predeterminadas para formatear y cosas por el estilo.

También tenga en cuenta que si su "nuestro" es la versión de copia de trabajo y no desea ser demasiado cauteloso, puede operar directamente en el archivo:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt

15

¿Son todas las modificaciones file.pyen branch2sus propias confirmaciones, separada de las modificaciones a otros archivos? Si es así, simplemente puede hacer cherry-picklos cambios:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

De lo contrario, mergeno funciona en rutas individuales ... también podría crear un git diffparche de file.pycambios branch2y de git applyellos a branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

8

Puedes stashy stash popel archivo:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

Esto sobrescribe branch1 / file.py con el contenido de branch2 / file.py en lugar de una fusión que debería generar un conflicto de fusión para resolver.
plumSemPy

2

Para fusionar solo los cambios de branch2 file.py, haga que los otros cambios desaparezcan.

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

Merge nunca mirará ningún otro archivo. Es posible que necesite '-f' los pagos si los árboles son lo suficientemente diferentes.

Tenga en cuenta que esto dejará a branch1 como si todo en el historial de branch2 hasta ese momento se hubiera fusionado, lo que puede no ser lo que desea. Probablemente sea una mejor versión del primer pago anterior

git checkout -B wip `git merge-base branch1 branch2`

en cuyo caso el mensaje de confirmación probablemente también debería ser

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

0

Estoy en la misma situación, quiero fusionar un archivo de una rama que tiene muchas confirmaciones en 2 ramas. Intenté muchas formas anteriores y otras que encontré en Internet y todas fallaron (porque el historial de confirmación es complejo), así que decido seguir mi camino (la forma loca).

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge

0

Lo que he hecho es un poco manual, pero yo:

  1. Fusionó las ramas normalmente; Revertió la fusión conrevert ;
  2. Revisé todos mis archivos a HEAD~1 , es decir, su estado en la confirmación de fusión;
  3. Rebasé mis confirmaciones para ocultar esta piratería del historial de confirmaciones.

¿Feo? Si. ¿Fácil de recordar? También si.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.