Comment fusionner les modifications dans un seul fichier, plutôt que de fusionner les validations?

383

J'ai deux branches (A et B) et je veux fusionner un seul fichier de la branche A avec un seul fichier correspondant de la branche B.

Isuru
la source
2
Déjà discuté ici stackoverflow.com/questions/449541/…
positron
27
La plupart des réponses à cet autre article concernent la fusion sélective des validations , pas des fichiers . Cela rend la réponse sélectionnée incorrecte. La question reste sans réponse.
Cette réponse est la voie à suivre, OMI. git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb

Réponses:

631

J'ai rencontré le même problème. Pour être précis, j'ai deux branches Aet Bavec les mêmes fichiers mais une interface de programmation différente dans certains fichiers. Maintenant, les méthodes de fichier f, qui sont indépendantes des différences d'interface dans les deux branches, ont été modifiées en branche B, mais la modification est importante pour les deux branches. Ainsi, je dois fusionner simplement le fichier fde branche Ben fichier fde branche A.

Une simple commande a déjà résolu le problème pour moi si je suppose que toutes les modifications sont validées dans les deux branches Aet B:

git checkout A

git checkout --patch B f

La première commande bascule en branche A, là où je veux fusionner Bla version du fichier f. La deuxième commande corrige le fichier favec fof HEADof B. Vous pouvez même accepter / supprimer des parties uniques du patch. Au lieu de cela, Bvous pouvez spécifier un commit ici, ce n'est pas obligatoire HEAD.

Modification de la communauté : si le fichier fsur Bn'existe pas Aencore, omettez l' --patchoption. Sinon, vous obtiendrez un "No Change". message.

loup
la source
10
Cela ne fonctionne que si vous souhaitez mettre à jour un fichier. Et si je veux ajouter un nouveau fichier de la branche B à la branche A?
Umair A.
25
@UmairAshraf, vous devriez pouvoir ajouter un nouveau fichier de B à A en supprimant l'option --patch.
bbak
9
Hmmm ... quand j'essaye, je reçois le message "pas de changement", mais il y a clairement des changements. OK, je devais être dans le dossier où se trouvait le fichier correspondant. Edit: Cela pourrait très probablement être ma solution préférée à un problème que j'ai vu sur stackoverflow :-D
bot_bot
2
J'ai dû utiliser git checkout --patch B -- fpour que cela fonctionne.
user545424
8
Il suffit d'ajouter que si vous avez plusieurs modifications (mecs) dans le fichier et que vous souhaitez toutes les mettre en scène , vous pouvez appuyer apendant la phase interactive, au lieu d'appuyer à ychaque fois. Ou utilisez git checkout B -- fplutôt la commande.
Dmitry
17

Voici ce que je fais dans ces situations. C'est un coup de coude mais cela fonctionne très bien pour moi.

  1. Créez une autre branche basée sur votre branche active.
  2. git pull / git fusionne la révision (SHA1) qui contient le fichier que vous souhaitez copier. Donc, cela fusionnera toutes vos modifications, mais nous n'utilisons cette branche que pour récupérer le seul fichier.
  3. Corrigez tous les conflits, etc. examinez votre fichier.
  4. vérifier votre branche de travail
  5. Extraire le fichier validé de votre fusion.
  6. Engagez-le.

J'ai essayé de patcher et ma situation était trop laide pour ça. Donc, en bref, cela ressemblerait à ceci:

Branche de travail: A Branche expérimentale: B (contient file.txt qui contient les modifications que je souhaite intégrer.)

git checkout A

Créez une nouvelle branche basée sur A:

git checkout -b tempAB

Fusionner B dans tempAB

git merge B

Copiez le hachage sha1 de la fusion:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <[email protected]>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

Vérifiez votre branche de travail:

git checkout A

Récupérez votre fichier corrigé:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

Et là, vous devriez l'avoir. Validez votre résultat.

oeufmatters
la source
3
Nous devons donc faire tout cela juste pour fusionner un seul fichier? Ne serait-il pas plus simple de copier et coller le fichier dans l'autre branche
Robin
1
@Robin probablement pas, car la fusion conserve les modifications dans le fichier, qui diffèrent entre la branche A et B. la copie du fichier remplacera toutes les différences supplémentaires entre votre branche de travail A et ce que vous vouliez apporter de B, qui ne peut pas contenir ces entrées / modifications. Par exemple, le suspect As'est détourné Bpour commencer, par d'autres moyens. La copie remplacera ces différences.
blamb
14

Cela utilise l'outil de diff interne de git. Peut-être un peu de travail à faire, mais simple.

#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.
Mikael Kellgren
la source
1
Pour clarifier l'utilisation de --(libellé d'argument vide), git checkout docs: ARGUMENT DISAMBIGUATION say: "à utiliser git checkout -- <pathspec>si vous souhaitez extraire ces chemins de l'index". En effet, vous pouvez avoir à la fois une branche et un fichier / chemin d'accès du même nom. Dans de tels cas, plutôt que de vous demander de lever l'ambiguïté si la branche ou le chemin doit être extrait quand les deux existent, git choisira de retirer la branche par défaut. Cependant, si --git précède, le fichier / chemin sera extrait à la place.
SherylHohman
8

J'ai trouvé cette approche simple et utile: comment «fusionner» des fichiers spécifiques d'une autre branche

Il s'avère que nous essayons trop fort. Notre bon ami git checkout est le bon outil pour le travail.

git checkout source_branch <paths>...

Nous pouvons simplement donner à git checkout le nom de la branche de fonctionnalité A et les chemins d'accès aux fichiers spécifiques que nous voulons ajouter à notre branche principale.

Veuillez lire l'article entier pour plus de compréhension

Pawel Cioch
la source
2
Cela écrase les fichiers, il ne les fusionne pas
Alex G
Pour vous, cela dépend de ce que vous faites et de ce que vous essayez de réaliser. L'idée ici est que la branche B est une fourchette de A, vous modifiez 4 fichiers en B, mais vous voulez fusionner seulement 2 de B en A. La fusion régulière fusionnerait les 4, ici vous pouvez sélectionner. Cela peut ressembler à leur remplacement car B contient essentiellement des fichiers plus récents. Vous devez étayer votre expérience avec des preuves.
Pawel Cioch
Je suis d'accord qu'il écrase. Je pense que vous vouliez utiliser l' -poption dans cette commande. Ce qui écrase alors toutes les parties de votre fichier Worktree qui ont déjà détourné de la branche de votre extraction, avant les modifications du correctif, malheureusement.
blamb
Eh bien, l'idée était de 2009, il y a de fortes chances que la nouvelle version de git se comporte différemment et ait besoin de -p ou de quoi que ce soit d'autre, mais quand je l'ai posté, cela fonctionnait pour moi, mais encore une fois, peut-être que je ne me souciais pas que les fichiers soient remplacés, comme la dernière version était ce dont j'avais besoin
Pawel Cioch
3

La commande suivante comparera (1) le fichier de la branche correcte, à master (2) vous demandera de manière interactive quelles modifications appliquer.

git checkout --patch master

user1854182
la source
0

Ma modification a été rejetée, donc j'attache ici comment gérer les modifications de fusion d'une branche distante ici.

Si vous devez le faire après une fusion incorrecte, vous pouvez faire quelque chose comme ceci:

# 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.
Soupe
la source
0

En supposant que B est la branche actuelle:

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

Notez que cela s'applique uniquement aux modifications apportées au fichier local. Vous devrez vous engager par la suite.

jbirkel
la source
Pour moi, cela génère unerror: <file-path>: already exists in working directory
kontur
Vous devez un fichier ou un chemin de fichier spécifique dans le répertoire en cours. J'utilisegit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri
0

Vous pouvez extraire l'ancienne version du fichier à fusionner, l'enregistrer sous un nom différent, puis exécuter quel que soit votre outil de fusion sur les deux fichiers.

par exemple.

git show B:src/common/store.ts > /tmp/store.ts (où B est le nom de la branche / commit / tag)

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

Salami
la source
0

Je le ferai comme

git format-patch branch_old..branch_new file

cela produira un patch pour le fichier.

Appliquer le correctif à la branche branch_old

git am blahblah.patch

Noob
la source
Pouvez-vous facilement examiner le patch pour plus de sécurité?
XavierStuvw