J'ai la disposition de référentiel suivante:
- branche maître (production)
- l'intégration
- travail
Ce que je veux réaliser, c'est de sélectionner une gamme de validations de la branche de travail et de la fusionner dans la branche d'intégration. Je suis assez nouveau sur git et je ne peux pas comprendre comment faire exactement cela (la sélection des plages de commit en une seule opération et non la fusion) sans gâcher le référentiel. Des conseils ou des réflexions à ce sujet? Merci!
git
git-merge
git-cherry-pick
crazybyte
la source
la source
Réponses:
En ce qui concerne une gamme de commits, la sélection des cerises
estn'était pas pratique.Comme mentionné ci-dessous par Keith Kim , Git 1.7.2+ a introduit la possibilité de sélectionner une gamme de validations (mais vous devez toujours être conscient des conséquences de la sélection à la cerise pour une fusion future )
damian commente et nous prévient:
Si vous voulez choisir la plage à
B
traversD
( y compris) ce seraitB^..D
.Voir " Git create branch from range of previous commits? " Comme illustration.
Comme le mentionne Jubobs dans les commentaires :
Remarque: à partir de Git 2.9.x / 2.10 (Q3 2016), vous pouvez sélectionner une plage de commit directement sur une branche orpheline (tête vide): voir " Comment faire d'une branche existante orpheline dans git ".
Réponse originale (janvier 2010)
Un
rebase --onto
serait mieux, où vous rejouez la plage de validation donnée au-dessus de votre branche d'intégration, comme Charles Bailey l'a décrit ici .(recherchez également "Voici comment vous transplanteriez une branche de sujet basée sur une branche à une autre" dans la page de manuel de git rebase , pour voir un exemple pratique de
git rebase --onto
)Si votre branche actuelle est l'intégration:
Cela rejouera tout entre:
first_SHA-1_of_working_branch_range
(d'où le~1
): le premier commit que vous souhaitez rejouerintegration
" (qui pointe vers le dernier commit que vous souhaitez rejouer, depuis laworking
branche)à "
tmp
" (qui indique oùintegration
pointait auparavant)En cas de conflit lors de la relecture de l'un de ces validations:
git rebase --continue
".git rebase --skip
"git rebase --abort
" (et remettre laintegration
branche sur latmp
branche)Après cela
rebase --onto
,integration
sera de retour au dernier commit de la branche d'intégration (c'est-à-dire "tmp
" branche + tous les commits rejoués)Avec la cueillette des cerises ou
rebase --onto
, n'oubliez pas que cela a des conséquences sur les fusions ultérieures, comme décrit ici .Une
cherry-pick
solution " " pure est discutée ici et impliquerait quelque chose comme:Mais de toute façon, lorsque vous devez "rejouer" une série de validations, le mot "rejouer" devrait vous pousser à utiliser la fonctionnalité "
rebase
" de Git.la source
-m
option, comment gérez-vous ces commits? Ou existe-t-il un moyen de filtrer ces commits?-m
est censé les gérer pour vous, en sélectionnant la ligne principale référencée par le-m
paramètre que vous avez choisi pour cette sélection.-m
option uniquement quand elle frappe un commit parent lors de la sélection de cerises de commits? En ce moment , si je passe-m
commegit cherry-pick a87afaaf..asfa789 -m 1
il applique à tous les commits dans la gamme.error: Commit 8fcaf3b61823c14674c841ea88c6067dfda3af48 is a merge but no -m option was given.
je réellement réalisé que vous pourriez justegit cherry-pick --continue
et ce serait bien (mais il ne comprendrait pas l'engagement des parents)Depuis git v1.7.2, Cherry Pick peut accepter une gamme de commits:
la source
cherry-pick A..B
le commit A ne sera pas obtenu (vous en aurez besoinA~1..B
), et s'il y a des conflits, git ne continuera pas automatiquement comme rebase (au moins à partir de 1.7.3.1)git cherry-pick A..B C
cela ne fonctionne pas comme vous vous en doutez, naïvement. Il ne choisira pas tout dans la gammeA..B
et s'engageC
! Pour ce faire, vous devez diviser en deux lignes, tout d' abordgit cherry-pick A..B
, puisgit cherry-pick C
. Ainsi, chaque fois que vous avez une plage, vous devez l'exécuter séparément.Supposons que vous ayez 2 branches,
"branchA": inclut les validations que vous souhaitez copier (de "commitA" à "commitB"
"branchB": la branche dont vous souhaitez que les validations soient transférées de "branchA"
1)
2) obtenir les ID de "commitA" et "commitB"
3)
4)
5) En cas de conflit, résolvez-le et saisissez
de poursuivre le processus de sélection.
la source
Êtes-vous sûr de ne pas vouloir réellement fusionner les branches? Si la branche de travail a des validations récentes que vous ne voulez pas, vous pouvez simplement créer une nouvelle branche avec une HEAD au point souhaité.
Maintenant, si vous voulez vraiment choisir une gamme de commits, pour une raison quelconque, une façon élégante de le faire est de simplement extraire un jeu de patchs et de l'appliquer à votre nouvelle branche d'intégration:
C'est essentiellement ce que git-rebase fait de toute façon, mais sans avoir besoin de jouer à des jeux. Vous pouvez ajouter
--3way
àgit-am
si vous avez besoin de fusionner. Assurez-vous qu'il n'y a pas d'autres fichiers * .patch déjà dans le répertoire où vous faites cela, si vous suivez les instructions textuellement ...la source
A^
inclusA
.J'ai encapsulé le code de VonC dans un court script bash
git-multi-cherry-pick
, pour une exécution facile:J'utilise actuellement cela alors que je reconstruis l'historique d'un projet qui avait à la fois du code tiers et des personnalisations mélangés dans le même tronc svn. Je sépare maintenant le code tiers principal, les modules tiers et les personnalisations sur leurs propres branches git pour une meilleure compréhension des personnalisations à venir.
git-cherry-pick
est utile dans cette situation car j'ai deux arbres dans le même référentiel, mais sans ancêtre partagé.la source
Toutes les options ci-dessus vous inviteront à résoudre les conflits de fusion. Si vous fusionnez des modifications validées pour une équipe, il est difficile de résoudre les conflits de fusion des développeurs et de continuer. Cependant, "git merge" fera la fusion en une seule fois mais vous ne pouvez pas passer une série de révisions en argument. nous devons utiliser les commandes "git diff" et "git apply" pour faire la plage de fusion des tours. J'ai remarqué que "git apply" échouera si le fichier de correctif présente des différences pour un trop grand nombre de fichiers, nous devons donc créer un correctif par fichier, puis appliquer. Notez que le script ne pourra pas supprimer les fichiers supprimés dans la branche source. Ceci est un cas rare, vous pouvez supprimer manuellement ces fichiers de la branche cible. Le statut de sortie de "git apply" n'est pas nul s'il n'est pas en mesure d'appliquer le patch,
Voici le script.
la source
Je l'ai testé il y a quelques jours, après avoir lu l'explication très claire de Vonc.
Mes pas
Début
dev
: ABCDEFGHIJtarget
: ABCDE
niH
Étapes pour copier des fonctionnalités sans les étapes E et H dans la branche
dev_feature_wo_E_H
git checkout dev
git checkout -b dev_feature_wo_E_H
git rebase --interactive --rebase-merges --no-ff D
où je metsdrop
devantE
etH
dans l'éditeur de rebasecommit
Étapes pour copier la branche
dev_feature_wo_E_H
sur la cible.git checkout target
git merge --no-ff --no-commit dev_feature_wo_E_H
commit
Quelques remarques
cherry-pick
les jours précédentsgit cherry-pick
est puissant et simple maismerge
je dois résoudre les conflits des validations initiales et des doublons, donc pour un ou deuxcherry-pick
, c'est OK de "choisir" mais pour plus c'est trop verbeux et la branche deviendra trop complexegit rebase --onto
la source
Une autre option pourrait être de fusionner avec la nôtre de la stratégie à la validation avant la plage, puis une fusion «normale» avec la dernière validation de cette plage (ou une branche lorsqu'elle est la dernière). Supposons donc que seuls 2345 et 3456 commits de master soient fusionnés dans la branche de fonctionnalité:
dans la branche de fonctionnalité:
la source