web-dev-qa-db-fra.com

Git cherry-pick syntax et merge branches

J'ai donc fait d'innombrables choix de cerises avant et il semble que je doive échouer dans la vie avec cela en ce moment, j'essaie de choisir une branche à une autre, ce qui devrait être facile, mais je reçois une erreur à propos de la fusion, mais pas -m a été donné?

$ git cherry-pick a8c5ad438f6173dc34f6ec45bddcef2ab23285e0
error: Commit a8c5ad438f6173dc34f6ec45bddcef2ab23285e0 is a merge but no -m option was given.
fatal: cherry-pick failed

Ça a l'air mal ... ça devrait être:

$ git cherry-pick a8c5ad438f6173dc34f6ec45bddcef2ab23285e0

Depuis quand dois-je fournir une fonction -m?

57
TheWebs

Vous devez fournir -m Si le commit est un merge commit, c'est-à-dire un commit avec plus d'un parent.

Normalement, ce que fait git cherry-pick REV Peut être décrit comme:

  1. Prenez les changements entre rev et son parent.

  2. Appliquez ces modifications au courant HEAD et validez le résultat avec le message de validation de rev.

Un commit de fusion rejoint deux lignes de développement. Par exemple, une ligne implémente un widget et l'autre ligne supprime l'encombrement. La fusion vous donne le code avec le widget, sans l'encombrement.

Considérez maintenant l'étape # 1 du processus de sélection: git ne peut pas deviner si vous voulez supprimer l'encombrement ou implémenter le widget. Vous ne pouvez pas non plus faire les deux, car les informations sur la façon de faire les deux ne sont pas contenues dans un seul commit de fusion, seul le contenu de l'arborescence fusionnée résultante l'est.

L'option -m Vous permet d'indiquer à git comment procéder. Par exemple, si la suppression de l'encombrement s'est produite sur master et que la validation de la fusion a été créée à l'aide de git merge WIDGET, Alors git cherry-pick -m 1 merged-commit Sélectionnera le nouveau widget car il y a une différence entre l'arborescence fusionnée et le parent 1 (la dernière des validations qui suppriment l'encombrement) aura été exactement l'ajout du widget. D'un autre côté, git cherry-pick -m 2 merge-commit Supprimera l'encombrement, car la différence entre le parent 2 (le dernier des validations d'ajout de widget) et fusion-validation est exactement l'élimination de l'encombrement manquante à partir de la branche widget.

74
user4815162342

Le git vous demande de spécifier le numéro de parent (-m), car votre commit de fusion a deux parents et git ne sait pas quel côté de la fusion doit être considéré comme la ligne principale. Donc, en utilisant cette option, vous pouvez spécifier le numéro de parent (à partir de 1) de la ligne principale et de la sélection afin de rejouer la modification par rapport au parent spécifié.

Pour connaître vos parents engagés, essayez soit:

git show --pretty=raw <merge_commit>

ou:

git cat-file -p <merge_commit>

ou même pour une meilleure visibilité de l'interface graphique, essayez:

gitk <merge_commit>

En conséquence, vous devriez obtenir quelque chose comme:

commit fc70b1e9f940a6b511cbf86fe20293b181fb7821
tree 8d2ed6b21f074725db4f90e6aca1ebda6bc5d050 
parent 54d59bedb9228fbbb9d645b977173009647a08a9 = <parent1_commit>
parent 80f1016b327cd8482a3855ade89a41ffab64a792 = <parent2_commit>

Vérifiez ensuite les détails de chaque parent en:

git show <parent1_or_2_commit>

Ajouter --stat pour voir la liste des fichiers modifiés.

Ou utilisez la commande suivante pour comparer les modifications (en fonction du parent ci-dessus):

git diff <parent1_or_2_commit>..<commit>

Ajouter --stat pour voir la liste des fichiers modifiés.

ou utilisez le diff combiné pour comparer les deux parents en:

git diff --cc <parent1_commit>
git diff --cc <parent2_commit>

Spécifiez ensuite le numéro de parent à partir de 1 pour votre choix, par ex.

git cherry-pick -m 1 <merge_commit>

Exécutez ensuite git status pour voir ce qui se passe. Si vous ne souhaitez pas encore valider les modifications, ajoutez -n option pour voir ce qui se passe. Ensuite, lorsque vous n'êtes pas satisfait, réinitialisez à HEAD (git reset HEAD --hard). Si vous rencontrez des conflits git, vous devrez probablement les résoudre manuellement ou spécifier une stratégie de fusion (-X), voir: Comment résoudre les conflits de fusion dans Git?

17
kenorb

Personnellement, ce que je fais normalement, c'est que, comme une fusion combine 2 validations, par exemple si j'ai une fusion, la validation C est composée de 2 parents, par exemple la validation A dans le maître et la validation B de l'autre branche fusionnée, si j'ai besoin de choisir le fusionner, je ne me dérangerais pas avec la commande déroutante de choisir le commit de fusion lui-même, mais au lieu de cela, je chérirais chacun des parents A et B individuellement, cela est également utile dans une situation où vous ne souhaitez sélectionner le commit B que dans validation de cas A du maître a déjà été sélectionné dans la branche vers laquelle la sélection est effectuée avant la fusion.

3
Wyclif

La syntaxe des pages de manuel est la suivante:

git cherry-pick [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...

Le numéro de parent fait référence à:

-m parent-number, --mainline parent-number, Habituellement, vous ne pouvez pas choisir une fusion car vous ne savez pas quel côté de la fusion doit être considéré comme la ligne principale. Cette option spécifie le numéro du parent (à partir de 1) de la ligne principale et permet à cherry-pick de rejouer la modification par rapport au parent spécifié.

Je voudrais donc vérifier pour vous assurer que vous disposez du hachage de validation correct. Il se peut que vous en vouliez un qui ne soit pas issu d'une fusion mais plutôt du commit avant lui. Sinon, vous devez utiliser cet indicateur et pointer du bon côté de la fusion pour lever l'ambiguïté de votre demande.

2
Magikhead