web-dev-qa-db-fra.com

En utilisant GIT, comment puis-je fusionner de manière sélective les modifications d'un commit sur un autre 'fork'?

Prenez ce scénario:

  1. Je décide de "bifurquer" une base de code sur github.com, et commence à faire ma routine: Edit - Commit - Push; aka hack hack hack.
  2. Après avoir apporté quelques modifications, je vois des modifications qu'une autre personne a apportées au même projet, et je les aime!
  3. Je décide que je veux les fusionner dans le mien. Le problème est que je ne veux qu'une "partie" d'un commit particulier, sur plusieurs commits qu'il a faits.

Quelle serait la méthode la plus efficace pour obtenir ces quantités sélectionnées de modifications, fusionnées dans mon "fork"?

79
Tim

Après avoir parcouru les vagues du monde IRC, quelqu'un a donné une excellente solution:

git cherry-pick SHA1 --no-commit
git add --patch

J'espère que cela aide quelqu'un d'autre avec la même question!

EDIT: OK, ce n'est peut-être pas aussi simple que cela. Voici les étapes complètes:

  1. Vous devez d'abord être dans votre référentiel, faites le cd- nécessaire pour accéder à votre répertoire de travail.

  2. Vous devez maintenant ajouter la branche distante, puis la récupérer. Pour ce faire:

    git remote add someUser git://github.com/someUser/someRepo.git

    git fetch someUser

  3. Vous pouvez maintenant exécuter des commandes telles que git log someUser/master pour trouver le commit SHA1 dans lequel vous souhaitez fusionner "partiellement".

  4. Une fois que vous avez le SHA, vous pouvez maintenant exécuter:

    git cherry-pick -n SHA1

    SHA1 est le commit SHA, duh!

  5. Il y aura très probablement des conflits, selon l'âge de la validation et la fréquence à laquelle cette zone particulière du projet change. Désolé, mais vous devez les résoudre manuellement avec votre fidèle éditeur. Alors, retirez VIM, ou tout ce que vous utilisez, et éloignez-vous des conflits jusqu'à ce que vous arriviez à l'étape où vous aimez les changements.

  6. Vous devez maintenant réinitialiser l'index à la révision HEAD, vous pouvez ensuite utiliser le fidèle GIT add --patch commande pour sélectionner et choisir les modifications que vous souhaitez:

    git reset HEAD

    git add --patch ou git add -p

  7. Yay! Temps de validation:

    git commit -m "I merged a select amount of changes"

  8. Pour nettoyer le gâchis (les trucs que vous avez dit non dans git add --patch) et conserver uniquement les modifications sélectionnées dans votre référentiel de travail, exécutez:

    git reset --hard HEAD

    Apparemment git checkout -f est également une autre option.

117
Tim

J'aime vraiment la solution de Tim, mais parfois j'aime bricoler dans vimdiff. Ma solution à ce problème est grossière, mais cela fonctionne pour moi car j'aime vim.

J'ai vimdiff défini comme mon outil de diff, puis pour fusionner sélectivement je diff la branche:

git difftool <branch> <file>

Ensuite, je vais dans le volet avec la version de la branche actuelle et édite l'original dans vim (parfois ce n'est pas nécessaire, mais parfois vimdiff ouvre une version dans/tmp) et désactive le mode lecture seule:

:e <file>
:set readonly!

Maintenant, je peux utiliser les outils de patch de vim tels que do et dp pour appliquer ce que je veux et apporter d'autres modifications au fur et à mesure. Lorsque j'ai terminé, j'enregistre le fichier, quitte la sortie de vim, puis met en scène et valide le fichier dans git comme une édition régulière.

Comme je l'ai dit, ce n'est pas particulièrement sophistiqué, mais il est très puissant et toujours purement en ligne de commande. Assurez-vous simplement d'ajouter un message de validation clair, car git n'inclura pas automatiquement un message de fusion pour vous.

exemple vimdiff http://j.mp/1dZVllt

2
Mike Dacre

Je ne sais pas exactement ce que tu veux. Si vous souhaitez importer uniquement certaines validations des autres fourches, vous pouvez utiliser git cherry-pick SHA. Explication complète sur gitready .

2
hgmnz

Si vous ne souhaitez que le port d'un commit, vous feriez probablement mieux de choisir le commit que vous souhaitez et de réinitialiser les fichiers que vous ne souhaitez pas toucher.

git cherry-pick SHA1
git checkout HEAD file1 file2 ... fileN

Bien sûr, si vous avez plusieurs pièces modifiées dans un fichier et que vous souhaitez uniquement en conserver certaines, vous n'avez pas d'autre choix que d'éditer le fichier manuellement, en supprimant leurs modifications.

1
Bombe