¿Cómo combino los cambios en un solo archivo, en lugar de fusionar confirmaciones?


383

Tengo dos ramas (A y B) y quiero fusionar un solo archivo de la rama A con un archivo único correspondiente de la Rama B.



27
La mayoría de las respuestas a esa otra publicación tratan sobre cómo combinar selectivamente confirmaciones , no archivos . Esto hace que la respuesta seleccionada sea incorrecta. La pregunta sigue sin respuesta.


Esta respuesta es el camino a seguir, en mi opinión. git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb el

Respuestas:


631

Me encontré con el mismo problema. Para ser precisos, tengo dos ramas Ay Bcon los mismos archivos pero una interfaz de programación diferente en algunos archivos. Ahora los métodos de archivo f, que es independiente de las diferencias de interfaz en las dos ramas, se cambiaron en rama B, pero el cambio es importante para ambas ramas. Por lo tanto, necesito fusionar solo el archivo fde rama Ben el archivo fde rama A.

Un simple comando ya resolvió el problema para mí si supongo que todos los cambios se confirman en ambas ramas Ay B:

git checkout A

git checkout --patch B f

El primer comando cambia a rama A, donde quiero fusionar Bla versión del archivo f. El segundo comando parchea el archivo fcon fde HEADof B. Incluso puede aceptar / descartar partes individuales del parche. En lugar de Bque pueda especificar cualquier confirmación aquí, no tiene que ser así HEAD.

Comunidad de edición : Si el archivo fen Bno existe en Atodavía, entonces omitir la --patchopción. De lo contrario, obtendrá un "Sin cambio". mensaje.


10
Esto solo funciona si desea actualizar un archivo. ¿Qué sucede si deseo agregar un nuevo archivo de la rama B a la rama A?
Umair A.

25
@UmairAshraf debería poder agregar un nuevo archivo de B a A eliminando la opción --patch.
bbak

99
Hmmm ... cuando intento esto recibo el mensaje "sin cambios", pero claramente hay cambios. OK, necesitaba estar en la carpeta donde estaba el archivo relevante. Editar: Esta podría ser mi solución favorita a un problema que he visto en stackoverflow :-D
bot_bot

2
Tuve que usar git checkout --patch B -- fpara que esto funcionara.
user545424

8
Solo tiene que agregar que si tiene varios cambios (trozos) en el archivo y desea organizarlos todos , puede presionar adurante la fase interactiva, en lugar de presionar ycada vez. O use el git checkout B -- fcomando en su lugar.
Dmitry Gonchar

17

Esto es lo que hago en estas situaciones. Es un error pero funciona bien para mí.

  1. Cree otra rama basada en su rama de trabajo.
  2. git pull / git combina la revisión (SHA1) que contiene el archivo que desea copiar. Por lo tanto, esto combinará todos sus cambios, pero solo estamos usando esta rama para tomar el único archivo.
  3. Arregle cualquier conflicto, etc. investigue su archivo.
  4. verifica tu rama de trabajo
  5. Verifique el archivo comprometido desde su fusión.
  6. Compromételo

Traté de parchar y mi situación era demasiado fea para eso. En resumen, se vería así:

Rama de trabajo: A Rama experimental: B (contiene file.txt que tiene los cambios que quiero plegar).

git checkout A

Crear una nueva sucursal basada en A:

git checkout -b tempAB

Fusionar B en tempAB

git merge B

Copie el hash sha1 de la fusión:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <matthewe@matthewe.com>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

Verifique su rama de trabajo:

git checkout A

Revise su archivo arreglado:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

Y ahí deberías tenerlo. Compromete tu resultado.


3
¿Entonces tenemos que hacer todo esto para fusionar un solo archivo? ¿No sería más fácil copiar y pegar el archivo en la otra rama
Robin

1
@Robin probablemente no, porque la fusión mantiene los cambios en el archivo, que difieren entre la rama A y B. al copiar el archivo se sobrescribirán las diferencias adicionales entre su rama de trabajo A y lo que desea traer de B, que puede no contener esas entradas / ediciones. Por ejemplo, el sospechoso se Aha desviado desde el Bprincipio, de otras maneras. Copiar sobrepasará esas diferencias.
blamb

14

Esto usa el difftool interno de git. Tal vez un poco de trabajo por hacer, pero sencillo.

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.

1
Para aclarar el uso de --(etiqueta de argumento vacía), git checkout docs: ARGUMENT DISAMBIGUATION dice: " úsalogit checkout -- <pathspec> si quieres retirar estas rutas del índice". Esto se debe a que podría tener tanto una rama como un archivo / ruta con el mismo nombre. En tales casos, en lugar de pedirle que desambigüe si la rama o la ruta deben desprotegerse cuando existan, git optará por pagar la rama de forma predeterminada. Sin embargo, si --precede a git, el archivo / ruta se descargará en su lugar.
SherylHohman

8

Este enfoque me pareció simple y útil: cómo "fusionar" archivos específicos de otra rama

Resulta que estamos intentando demasiado. Nuestro buen amigo git checkout es la herramienta adecuada para el trabajo.

git checkout source_branch <paths>...

Simplemente podemos dar a git checkout el nombre de la rama A de la característica y las rutas a los archivos específicos que queremos agregar a nuestra rama maestra.

Por favor lea el artículo completo para más comprensión


2
Esto sobrescribe los archivos, no los fusiona
Alex G

Para ti podría depender de lo que estás haciendo y de lo que estás tratando de lograr. La idea aquí es que la rama B es una bifurcación de A, modifica 4 archivos en B, pero desea fusionar solo 2 de B a A. La fusión regular fusionaría los 4, aquí puede seleccionar. Esto puede parecer que fueron anulados porque B contiene esencialmente archivos más nuevos. Necesita respaldar su experiencia con alguna evidencia.
Pawel Cioch

Estoy de acuerdo en que se sobrescribe. Creo que te refieres a usar la -popción en ese comando. Lo cual, luego, sobrescribe cualquier parte de su archivo de árbol de trabajo que se haya desviado previamente de la rama desde la que desprotegió, antes de los cambios del parche, desafortunadamente.
blamb

Bueno, la idea era de 2009, lo más probable es que la nueva versión de git se comporte de manera diferente y necesite -p o cualquier otra cosa, pero cuando la publicaba funcionaba para mí, pero tal vez no me importaba que los archivos se anularan, ya que la última versión era lo que necesitaba
Pawel Cioch


3

El siguiente comando (1) comparará el archivo de la rama correcta, a master (2) le preguntará interactivamente qué modificaciones aplicar.

git checkout - parche maestro


0

Mi edición fue rechazada, así que adjunto aquí cómo manejar los cambios de fusión desde una rama remota.

Si tiene que hacer esto después de una fusión incorrecta, puede hacer algo como esto:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.

0

Suponiendo que B es la rama actual:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

Tenga en cuenta que esto solo aplica cambios al archivo local. Tendrás que comprometerte después.


Para mí esto genera unerror: <file-path>: already exists in working directory
kontur

Debe especificar el archivo o la ruta del archivo en el directorio actual. Estoy en usogit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri

0

Puede verificar la versión anterior del archivo para fusionarlo, guardarlo con un nombre diferente y luego ejecutar la herramienta de fusión que esté en los dos archivos.

p.ej.

git show B:src/common/store.ts > /tmp/store.ts (donde B es el nombre de la sucursal / commit / tag)

meld src/common/store.ts /tmp/store.ts


0

Lo haré como

git format-patch branch_old..branch_new file

Esto producirá un parche para el archivo.

Aplicar parche en el destino branch_old

git am blahblah.patch


¿Puedes mirar fácilmente el parche para mayor seguridad?
XavierStuvw
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.