Comment sélectionner uniquement les modifications pour un seul fichier, pas pour tout le commit

108

Je dois appliquer les changements introduits dans une branche à une autre branche. Je peux utiliser la sélection de cerises pour faire cela. Cependant, dans mon cas, je souhaite appliquer des modifications qui ne sont pertinentes que pour un seul fichier, je n'ai pas besoin de sélectionner le commit entier. Comment faire ça?

comme lui
la source

Réponses:

137

Vous avez différentes options en fonction de ce que vous souhaitez réaliser:

Si vous souhaitez que le contenu du fichier soit le même que celui de la branche cible, vous pouvez utiliser git checkout <branch> -- <filename>. Cependant, cela ne «sélectionnera pas» les changements qui se sont produits dans un seul commit, mais prendra simplement l'état résultant dudit fichier. Donc, si vous avez ajouté une ligne dans un commit, mais que les commits précédents ont davantage changé, et que vous voulez seulement ajouter cette ligne sans ces autres changements, alors une extraction n'est pas ce que vous voulez.

Sinon, si vous souhaitez appliquer le correctif introduit dans un commit à un seul fichier, vous avez plusieurs options. Vous pouvez exécuter git cherry-pick -n, c'est-à-dire sans le valider, éditer le commit (par exemple réinitialiser tous les fichiers en utilisant git reset -- .et ajouter uniquement le fichier que vous voulez réellement changer en utilisant git add <filename>). Ou vous pouvez créer le diff pour le fichier et appliquer le diff alors:

git diff <branch>^..<branch> -- <filename> | git apply
poussée
la source
22

Créez un patch fileet appliquez-le.

git diff branchname -- filename > patchfile
git apply patchfile

ÉDITER:

Puisque vous devez prendre les modifications d'un commit, créez le correctif comme ceci:

git show sha1 -- filename > patchfile
Sailesh
la source
1
git diff sha1(ou git diff branch- c'est la même chose si la branche pointe vers le même hachage) ne produira qu'un diff du répertoire de travail actuel par rapport à ce hachage, mais pas ce qui change un commit introduit seul.
poke le
Correct. Modifié la réponse. Merci.
Sailesh
1
-1 git checkoutavec un nom de fichier est le bon marteau pour ce clou. Ces deux options sont inutilement complexes.
Rein Henrichs
7
Pour ce cas particulier, oui. Mais en général, si vous souhaitez sélectionner des modifications d'un commit apporté à un fichier particulier, checkoutcela ne fonctionnera pas, car cela peut impliquer d'autres modifications précédentes indésirables et peut ne pas contenir les modifications apportées dans la branche actuelle.
Sailesh
11

Une autre chose pratique à faire est d'obtenir le correctif localement, puis d'utiliser:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

Ce n'est cependant pas une sélection.

0x90
la source
2
Attention: comme @poke le dit dans sa réponse, cela ne recopie pas les changements; il copie l'état complet du fichier. Donc, si vous voulez ajouter les changements d'un commit au fichier, alors en vérifiant comme ça vous finissez par écraser les changements plus récents qui ne sont pas bons.
Alexander Bird
7

Git a tout prêt :)

Juste utiliser git checkout <sha> <path-to-file>

Raghotham S
la source
4
Ce n'est pas un choix de choix - qui vérifie le fichier dans son intégralité. Le but est de faire un changement particulier à partir d'un commit. C'est souvent la même chose, mais parfois non.
AndrewF
6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

cela fonctionne si vous voulez qu'un seul fichier d'une autre branche soit copié dans la branche de travail actuelle

Ismail Iqbal
la source
1
Attention, les modifications effectuées dans le fichier qui ne sont pas dans la version de l'autre branche seront perdues.
Patrick Schlüter
D'accord avec cela. ceci est utile si vous avez juste besoin d'une copie du fichier et que vous souhaitez le modifier sur la branche actuelle
Ismail Iqbal
1
On peut utiliser des globs (chemin / *) et spécifier plus d'un chemin / fichier
Todd
1

Voici ce que vous recherchez:

git checkout target-branch sha1 path/to/file

sha1 est facultatif

Ruslan Osipov
la source
11
non, "pick changes in commit" n'est pas "pick whole file"
Abyx
1

Ce que j'ai tendance à faire, c'est d'utiliser git ls-tree

fais juste:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

Cela affichera tous les noms de fichiers correspondant à votre grep et donnera les clés SHA1 des fichiers dans le commit.

Git show peut également être utilisé sur des fichiers en dehors de votre branche. l'utilisation >de votre shell pour diriger la sortie dans un fichier vous donne le résultat que vous recherchez.

Alex
la source
0

Vous pouvez essayer de faire ceci:

git show COMMIT_ID -- path/to/specific-file | git apply

Par exemple:

git show 3feaf20 -- app/views/home/index.html | git apply
arashb31
la source
-9
git reset HEAD~1

déplace les fichiers vers l'étape de pré-validation

git stash

supprime de la mémoire

Maintenant, votre branche est assez propre (retour au commit précédent)

Venkata
la source