web-dev-qa-db-fra.com

Comment fusionner des fichiers spécifiques à partir de branches Git

J'ai 2 branches git branch1 et branch2 et je veux fusionner file.py dans branch2 dans file.py dans branch1 et uniquement ce fichier.

En substance, je veux juste travailler sur le fichier file.py dans branch1, mais je veux profiter de la commande de fusion. Quelle est la meilleure façon de procéder?

155
rwolst

La réponse acceptée mentionne déjà l'utilisation de git checkout. Maintenant, il pourrait y avoir un contenu dans file.py de branch2 qui n’est plus applicable dans branch1. Une telle situation nécessitera de choisir certains changements et de laisser les autres. Par conséquent, pour avoir le contrôle total, effectuez une fusion interactive à l'aide du commutateur --patch:

$ git checkout --patch branch2 file.py

La section du mode interactif de la page de manuel de git-add(1) explique les touches à utiliser:

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

La commande split est particulièrement utile.

181
pdp

Comme indiqué dans les commentaires, il ne s’agit techniquement pas d’une "fusion", raison pour laquelle le lien ci-dessous utilise des guillemets. Cependant, j'ai rarement besoin de quelque chose d'aussi compliqué que le décrivent les autres affiches. Je pense donc que c'est une solution utile, sinon appropriée, à la question du PO.

Consultez cette page: Astuce Git: Comment "fusionner" des fichiers spécifiques d’une autre branche C’est le moyen le plus simple de le faire, à mon humble avis.

En gros, pour l’appliquer à votre situation:

$ git checkout branch1 # i.e. make sure you're in branch1
$ git checkout branch2 file.py

Peasy facile, file.py est maintenant dans branch1.

99

Toutes les modifications apportées à file.py dans branch2 dans leurs propres validations sont-elles distinctes des modifications apportées à d'autres fichiers? Si c'est le cas, vous pouvez simplement cherry-pick les modifications apportées:

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

Sinon, merge ne fonctionne pas sur des chemins individuels ... vous pouvez aussi simplement créer un patch git diff de file.py qui passe de branch2 à git apply en branch1:

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

Aucune des autres réponses actuelles ne "fusionnera" les fichiers, comme si vous utilisiez la commande de fusion. (Au mieux, vous devrez choisir manuellement les diff.) Si vous souhaitez réellement tirer parti de la fusion en utilisant les informations d'un ancêtre commun, vous pouvez suivre une procédure basée sur celle trouvée dans le "Fusion avancée"). section du manuel de référence de git.

Pour ce protocole, je suppose que vous souhaitez fusionner le fichier 'chemin/vers/fichier.txt' de Origin/master dans HEAD - modifiez-le selon vos besoins. (Vous n'êtes pas obligé d'être dans le répertoire principal de votre référentiel, mais cela aide.)

# 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 doit utiliser tous vos paramètres de fusion par défaut pour le formatage, etc.

Notez également que si votre "nôtre" est la version de travail et que vous ne voulez pas être trop prudent, vous pouvez agir directement sur le fichier:

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
11
R.M.

Vous pouvez stash et stash pop le fichier:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
6
Martin G

Pour fusionner uniquement les modifications du file.py de branch2, supprimez les autres modifications.

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 ne regardera jamais aucun autre fichier. Vous aurez peut-être besoin de '-f' les caisses si les arbres sont suffisamment différents.

Notez que cela laissera branche1 comme si tout ce qui se trouvait dans l'historique de branche2 à ce stade avait été fusionné, ce qui peut ne pas être ce que vous voulez. Une meilleure version de la première commande ci-dessus est probablement

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

auquel cas le message commit devrait probablement aussi être

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

Je suis dans la même situation, je veux fusionner un fichier d'une branche qui a beaucoup de commits sur 2 branches. J'ai essayé beaucoup de façons ci-dessus et d'autres que j'ai trouvées sur Internet et qui ont toutes échoué (parce que l'histoire de validation est complexe), alors j'ai décidé de faire ce que je voulais (à la manière folle).

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
Trac Nguyen