git - sauter des validations spécifiques lors de la fusion

200

J'utilise Git depuis environ un an maintenant et je pense que c'est fantastique, mais je viens de commencer une deuxième version du projet et j'ai commencé une nouvelle branche pour celui-ci. Je me bats un peu avec la meilleure façon de gérer les choses à l'avenir.

J'ai deux branches appelées dites master10 (pour v1) et master20 (pour v2). J'ai fait des corrections de bogues dans la v1 sur la branche master10 et développé de nouvelles choses de master20. Chaque fois que je fais un correctif de bogue, je le fusionne dans la v2 en vérifiant master20 et en le faisant git merge master10. Jusqu'ici tout va bien.

Maintenant, cependant, j'ai fait une modification dans la v1 que je ne veux pas dans la v2, mais je veux continuer à fusionner d'autres correctifs de bogues. Comment puis-je dire à Git d'ignorer ce commit particulier (ou une série de commits), mais qu'à l'avenir, je veux toujours fusionner d'autres corrections de bugs.

J'ai pensé git rebaseque c'était peut-être ce dont j'avais besoin, mais j'ai lu le document et ma tête a presque explosé.

Je pense que ce que je veux, c'est quelque chose comme une commande "git sync" qui dit à git que deux branches sont maintenant synchronisées et à l'avenir ne fusionneront les validations qu'à partir de ce point de synchronisation.

Toute aide appréciée.

Brad Robinson
la source

Réponses:

289

Par exemple, si vous souhaitez fusionner la plupart des validations de la branche "maint" vers "master", mais pas toutes. Cela nécessite un peu de travail ---- comme mentionné ci-dessus, le cas d'utilisation habituel est de tout fusionner à partir d'une branche --- mais il arrive parfois que vous apportiez une modification à une version finale qui ne devrait pas être réintégrée (peut-être que le code est déjà été remplacé par le maître), alors comment représentez-vous cela? Voici...

Supposons donc que maint ait appliqué 5 modifications, et l'une d'entre elles (maint ~ 3) ne doit pas être réintégrée dans master, bien que toutes les autres devraient l'être. Vous faites cela en trois étapes: fusionnez tout avant celui-ci, dites à git de marquer maint ~ 3 comme fusionné même quand ce n'est pas le cas, puis fusionnez le reste. La magie c'est:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

La première commande fusionne tout avant votre commit de maintenance gênante sur le maître. Le message par défaut du journal de fusion vous expliquera que vous fusionnez "branch 'maint' (early part)".

La deuxième commande fusionne le commit gênant maint ~ 3, mais l'option "-s ours" indique à git d'utiliser une "stratégie de fusion" spéciale qui, en fait, fonctionne simplement en gardant l'arborescence dans laquelle vous fusionnez et en ignorant le commit (s ) vous fusionnez complètement. Mais il fait toujours un nouveau commit de fusion avec HEAD et maint ~ 3 en tant que parents, donc le graphique de révision indique maintenant que maint ~ 3 est fusionné. Donc, en fait, vous voulez probablement utiliser l'option -m pour 'git merge' également, pour expliquer que cette validation maint ~ 3 est en fait ignorée!

La commande finale fusionne simplement le reste de maint (maint ~ 2..maint) dans master afin que vous soyez tous à nouveau synchronisés.

araqnid
la source
5
Je pense que si vous devez reporter la fusion de ce commit, vous n'avez pas d'autre choix que de le sauter (fusionner le nôtre) et de l'appliquer plus tard en utilisant la commande cherry-pick. Une fois que le commit est accessible depuis master, il ne peut plus être fusionné - éviter de fusionner deux fois le même changement est l'un des principaux objectifs de git.
araqnid
3
En ce qui concerne votre exemple de sous-branche: je soupçonne qu'une fois que vous avez fusionné la sous-branche, vous êtes exactement dans la même situation que vous êtes après la deuxième étape de mon message. La création de branches supplémentaires ne fait aucune différence pour les relations de validation.
araqnid
5
Juste par intérêt, si vous voulez simplement omettre un changement, pourquoi ne feriez-vous pas simplement une seule fusion, puis revenez-en à ce jeu de modifications, plutôt que d'effectuer trois fusions? Il en résulterait moins de modifications apportées au référentiel et un historique plus explicite.
Mark Booth
3
Il est souvent plus facile de nommer explicitement les commits. Il vous suffit donc de consulter le journal git de la branche à fusionner et de noter les hachages du commit qui ne devraient pas être fusionnés et celui d'avant - au lieu de compter les commits…
zwirbeltier
14
@MarkBooth: Le vous engage voulez sauter peut - être dans un énorme conflit avec la branche que vous souhaitez fusionner dans Il est plus facile de sauter au lieu de fixer les conflits alors que le changement de revenir et fixant les conflits à nouveau.
SztupY
39

À mon humble avis , la chose la plus logique à faire est de tout fusionner, puis d'utiliser git revert (commit_you_dont_want) pour le supprimer .

Exemple:

git merge master
git revert 12345678

Si vous avez plusieurs validations "à ignorer" ou si vous souhaitez modifier le message de retour:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Ensuite, votre histoire peut ressembler à:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

Si vous avez des conflits impliquant UNIQUEMENT ces commits "à ignorer", vous pouvez utiliser:

git merge master -X ours

Votre version persistera donc sur l'autre. Même sans messages d'erreur, vous pouvez toujours "annuler" ces validations indésirables, car elles peuvent avoir d'autres modifications qui ne sont pas en conflit, et vous ne les voulez toujours pas.

Si vous avez des conflits impliquant NON SEULEMENT les validations "à ignorer", vous devez les résoudre manuellement et vous devrez probablement les résoudre à nouveau lors de la restauration.

Alexandre T.
la source
2
Si vous souhaitez ensuite fusionner ces validations annulées dans la branche en question, Git les ignorera-t-il toujours?
Anriëtte Myburgh
@ AnriëtteMyburgh Vous pouvez annuler les validations de réversion pour les fusionner plus tard dans quelque chose que vous ne pouvez pas faire aussi facilement avec la stratégie "fusionner les nôtres".
Lily Chung
Merci, c'est exactement ce dont j'avais besoin avait quelques commits plus anciens dans une branche de fonctionnalité que je ne voulais pas dans master et un tas que je voulais dans master. Agréable et propre.
Vale Trujillo
17

Les engagements incluent l'ascendance. Vous ne pouvez pas fusionner une validation sans fusionner les validations précédentes.

Vous pouvez bien sûr les choisir. C'est un bon flux lorsque vous avez une branche en mode maintenance.

Dustin
la source
1
Merci, le choix de cerise fera le travail. Pas aussi bien que ce que j'espérais mais ça ira.
Brad Robinson, le
3

Une sorte de publicité pour mon projet qui enveloppe essentiellement le processus décrit par @araqnid.

C'est une sorte d'aide qui introduit le flux GIT suivant:

  • il y a une notification quotidienne / hebdomadaire sur les fusions en attente des branches de maintenance dans la branche dev / master
  • Le responsable de succursale vérifie le statut et décide lui-même si toutes les validations sont requises et en bloque certaines ou demande aux développeurs de se bloquer. À la fin, la branche de maintenance est fusionnée dans la partie amont.

Une citation de la page du projet:

Selon le flux de travail, il est possible d'avoir des succursales de maintenance ou spécifiques au client avec la branche principale. Ces branches sont également appelées branches LTS.

Souvent, les correctifs vont dans les branches où le bogue a été signalé, puis la validation est réintégrée dans la branche principale.

La pratique générale est d'avoir toutes les branches parfaitement synchronisées avec le maître, c'est-à-dire que vous voulez voir un delta clair entre une branche particulière et le maître pour comprendre si le maître contient toutes les fonctionnalités et corrections de bugs.

Cependant, parfois, vous ne voulez pas de validations particulières car elles sont spécifiques au client et ne doivent pas être visibles par les autres utilisateurs. Ou votre branche principale a tellement divergé qu'elle nécessite une approche complètement différente pour résoudre le problème, ou mieux encore, le problème n'y est plus présent.

De plus, en cas de sélection de cerise du maître dans la branche de maintenance, la validation résultante doit être bloquée dans le maître.

Dmytro
la source
0

Créez une troisième branche pour les modifications que vous souhaitez dans master10 mais pas dans master20. Considérez toujours master10 comme votre "master", la branche la plus stable de toutes. La branche avec laquelle toutes les autres branches souhaitent rester synchronisées à tout moment.

wilhelmtell
la source
Je suppose que cela pourrait fonctionner, mais je me suis déjà retrouvé dans cet état, et une troisième branche me perturberait probablement encore plus. :)
Brad Robinson
0

Plutôt que revertoucherry-pick dans ce cas, vous devez obtenir git pour tenir compte des changements que vous Skipping être plus vieux que ceux que vous avez fait.

Alors:

  1. fusionnez le dernier commit avant les commits que vous souhaitez ignorer. Bien entendu, cela fusionnera tous les commits antérieurs. git merge ccc
  2. fusionnez les validations que vous souhaitez ignorer. git merge fff --no-commit
  3. étape toutes les fusions, annuler toutes les modifications, annuler toutes les modifications. (Il existe peut-être des commandes infaillibles pour cela, mais je ferais juste cette partie dans une interface utilisateur - mais vous savez comment)
  4. terminer la fusion vide git merge --continue
  5. fusionnez les validations APRÈS celle que vous souhaitez ignorer. git merge source-branch-head

Après l'étape 4, git considérera votre branche plus récente que ce commit, puisque vous l'avez déjà traitée (en choisissant de conserver VOS versions des choses).

Jason Kleban
la source