Comment git-cherry-pick ne modifie que certains fichiers?

Si je veux fusionner en une branche Git les changements à certains des fichiers modifiés dans un commit qui comprend des modifications à plusieurs fichiers, comment cela peut-il être atteint?

supposons que la propagation de Git appelée stuff a des changements dans les fichiers A , B , C , et D mais je veux fusionner seulement les modifications de stuff aux fichiers A et B . Cela ressemble à un travail pour git cherry-pick mais cherry-pick seul sait comment fusionner ensemble s'engage, pas un sous-ensemble des fichiers.

405
demandé sur techdreams 2011-04-19 17:22:54

10 réponses

je le ferais avec cherry-pick -n ( --no-commit ) qui vous permet d'inspecter (et modifier) le résultat avant de commettre:

git cherry-pick -n <commit>

# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>

# commit; the message will have been stored for you by cherry-pick
git commit

si la grande majorité des modifications sont des choses que vous ne voulez pas, au lieu de vérifier les chemins individuels (étape du milieu), vous pouvez Tout réinitialiser, puis ajouter ce que vous voulez:

# unstage everything
git reset HEAD

# stage the modifications you do want
git add <path>

# make the work tree match the index
# (do this from the top level of the repo)
git checkout .
498
répondu Cascabel 2011-04-19 14:04:56

les autres méthodes n'ont pas fonctionné pour moi puisque le commit a eu beaucoup de changements et de conflits avec beaucoup d'autres fichiers. Ce que j'ai trouvé était tout simplement

git show SHA -- file1.txt file2.txt | git apply -

Il ne fait pas add les fichiers ou faire un commit pour vous afin que vous pouvez avoir besoin de suivre avec

git add file1.txt file2.txt
git commit -c SHA

ou si vous voulez sauter l'add, vous pouvez utiliser l'argument --cached pour git apply

git show SHA -- file1.txt file2.txt | git apply --cached -
94
répondu Michael Anderson 2018-05-17 04:13:28

peut-être l'avantage de cette méthode sur la réponse de Jefromi est que vous ne devez pas vous rappeler quel comportement de git reset est le bon:)

 # Create a branch to throw away, on which we'll do the cherry-pick:
 git checkout -b to-discard

 # Do the cherry-pick:
 git cherry-pick stuff

 # Switch back to the branch you were previously on:
 git checkout -

 # Update the working tree and the index with the versions of A and B
 # from the to-discard branch:
 git checkout to-discard -- A B

 # Commit those changes:
 git commit -m "Cherry-picked changes to A and B from [stuff]"

 # Delete the temporary branch:
 git branch -D to-discard
38
répondu Mark Longair 2017-05-23 12:26:38

j'utilise habituellement le drapeau -p avec une caisse git de l'autre branche que je trouve plus facile et plus granulaire que la plupart des autres méthodes que j'ai rencontrées.

en principe:

git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p

exemple:

git checkout mybranch config/important.yml app/models/important.rb -p

vous obtenez alors un dialogue vous demandant quels changements vous voulez dans "blobs" cela fonctionne assez bien à chaque morceau de code continu changement que vous pouvez ensuite signaler y (Oui) n (Non) etc pour chaque morceau de code.

l'option -p ou patch fonctionne pour une variété de commandes en git y compris git stash save -p qui vous permet de choisir ce que vous voulez cacher de votre travail actuel

j'utilise parfois cette technique quand j'ai fait beaucoup de travail et que je voudrais la séparer et m'engager dans plus de sujets basés sur commits en utilisant git add -p et le choix de ce que je veux pour chaque commit :)

37
répondu Tyrone Wilson 2016-03-02 09:19:45
"151920920 '" écrémer est de choisir les modifications à partir d'un "commit". La solution la plus simple est de choisir tous les changements de certains fichiers est d'utiliser

 git checkout source_branch <paths>...

dans l'exemple:

$ git branch
* master
  twitter_integration
$ git checkout twitter_integration app/models/avatar.rb db/migrate/20090223104419_create_avatars.rb test/unit/models/avatar_test.rb test/functional/models/avatar_test.rb
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   app/models/avatar.rb
#   new file:   db/migrate/20090223104419_create_avatars.rb
#   new file:   test/functional/models/avatar_test.rb
#   new file:   test/unit/models/avatar_test.rb
#
$ git commit -m "'Merge' avatar code from 'twitter_integration' branch"
[master]: created 4d3e37b: "'Merge' avatar code from 'twitter_integration' branch"
4 files changed, 72 insertions(+), 0 deletions(-)
create mode 100644 app/models/avatar.rb
create mode 100644 db/migrate/20090223104419_create_avatars.rb
create mode 100644 test/functional/models/avatar_test.rb
create mode 100644 test/unit/models/avatar_test.rb

Sources et explication complète http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/

mise à jour:

avec cette méthode, git ne fusionnera pas le fichier, il va juste annuler tout autre changement fait sur la branche de destination. Vous devrez fusionner les modifications manuellement:

$ git diff TÊTE de nom de fichier

17
répondu cminatti 2013-12-18 19:44:16

je voudrais juste cherry-pick tout, puis faire ceci:

git reset --soft HEAD^

alors je retournerais les changements que je ne veux pas, puis je ferais un nouveau commit.

9
répondu funroll 2014-08-11 21:20:09

Utiliser git merge --squash branch_name cela permettra d'obtenir toutes les modifications de l'autre branche et préparera un commit pour vous. Maintenant, supprimez tous les changements inutiles et laissez celui que vous voulez. Et git ne saura pas qu'il y a eu une fusion.

8
répondu Indomitable 2017-10-30 17:02:36

j'ai trouvé un autre moyen qui empêche toute fusion conflictuelle sur cherry-picking qui IMO est en quelque sorte facile à se rappeler et à comprendre. Puisque vous n'êtes pas vraiment en train de choisir un commit, mais une partie de celui-ci, vous devez le partager d'abord et ensuite créer un commit qui conviendra à vos besoins et le choisir.

créer D'abord une branche à partir de la propagation que vous voulez diviser et la vérifier:

$ git checkout COMMIT-TO-SPLIT-SHA -b temp

puis revenir sur la Commission précédente:

$ git reset HEAD~1

puis ajoutez les fichiers / modifications que vous voulez sélectionner:

$ git add FILE

et de s'engager:

$ git commit -m "pick me"

notez le hachage de commit, appelons-le PICK-SHA et retournez à votre branche principale, maître par exemple forcer la caisse:

$ git checkout -f master

et de choisir le commettre:

$ git cherry-pick PICK-SHA

maintenant vous pouvez supprimer la branche temp:

$ git branch -d temp -f
3
répondu Alexey 2017-02-15 21:57:41

fusionner une branche dans une nouvelle (squash) et supprimer les fichiers inutiles:

git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit
1
répondu nvd 2018-04-11 14:04:16

la situation:

Vous êtes sur votre branche, disons-le, master et vous avez votre livraison sur toute autre branche. Vous ne devez choisir qu'un seul fichier de cette propagation particulière.

L'approche:

Étape 1: check-out sur la branche requise.

git checkout master

Étape 2: assurez-vous que vous avez copié la nécessaire commettre hachage.

git checkout commit_hash path\to\file

Étape 3: vous avez maintenant les changements du fichier requis sur votre branche désirée. Il suffit de les ajouter et de les engager.

git add path\to\file
git commit -m "Your commit message"
0
répondu techdreams 2018-08-07 05:52:43