Comment copier des validations d'une branche à une autre?


728

J'ai deux branches de mon maître:

  • v2.1 : (version 2) sur lequel je travaille depuis plusieurs mois
  • wss : que j'ai créé hier pour ajouter une fonctionnalité spécifique à mon master (en production)

Existe-t-il un moyen de copier les validations d'hier de wss vers la v2.1?


Pour copier simplement les validations (ou une gamme de validations) d'une branche à une autre, cette réponse m'a le mieux aidé: stackoverflow.com/questions/1994463/…
caramba

Réponses:


566

Vous devriez vraiment avoir un workflow qui vous permet de tout faire en fusionnant:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

Donc, tout ce que vous avez à faire est git checkout v2.1et git merge wss. Si, pour une raison quelconque, vous ne pouvez vraiment pas le faire et que vous ne pouvez pas utiliser git rebase pour déplacer votre branche wss au bon endroit, la commande pour récupérer un seul commit quelque part et l'appliquer ailleurs est git cherry-pick . Vérifiez simplement la branche sur laquelle vous souhaitez l'appliquer et exécutez git cherry-pick <SHA of commit to cherry-pick>.

Certaines des façons dont le rebasage peut vous sauver:

Si votre histoire ressemble à ceci:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

Vous pouvez utiliser git rebase --onto v2 v2-only wsspour déplacer wss directement sur la v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Ensuite, vous pouvez fusionner! Si vous ne pouvez vraiment, vraiment, vraiment pas arriver au point où vous pouvez fusionner, vous pouvez toujours utiliser rebase pour effectuer efficacement plusieurs sélections à la fois:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Remarque: la raison pour laquelle cela nécessite un travail supplémentaire est de créer des validations en double dans votre référentiel. Ce n'est pas vraiment une bonne chose - le but de la branchement et de la fusion faciles est de pouvoir tout faire en faisant des commit un seul endroit et en les fusionnant là où ils sont nécessaires. Les commits en double signifient une intention de ne jamais fusionner ces deux branches (si vous décidez de le faire plus tard, vous aurez des conflits).


1
Je ne pourrais pas être plus d'accord avec cette réponse. +1. Voir aussi mon ancienne réponse pour illustrer les conséquences de la cueillette des cerises: stackoverflow.com/questions/881092/…
VonC

18
Superbe réponse sur la façon de procéder correctement ! J'aimerais pouvoir voter à deux reprises pour l'effort de création de diagrammes ASCII également.
gotgenes

@VonC: Merci pour le soutien et les informations supplémentaires sur pourquoi ne pas choisir - je sais que j'ai lésiné un peu là-bas. @gotgenes: Merci! Je pense que cela en vaut vraiment la peine - il suffit de regarder la page de manuel git-rebase. Il n'y a pas de meilleure façon de l'expliquer.
Cascabel

Quant à savoir pourquoi vous ne pourrez peut-être pas fusionner - la fusion de Git ne fonctionne pas bien avec git-svn. Pour copier une série de validations d'une branche SVN à une autre, j'ai fini par les sélectionner et ensuite effectuer un rebase / reformulation interactif pour supprimer les git-svn-idréférences incorrectes avant de dcommitréingérer. Bien que j'aurais probablement pu laisser de côté l'étape de sélection de cerise et juste utiliser un rebase seul.
Bob

1
Voici mon cas d'utilisation: des corrections de bogues critiques ont été validées dans la branche des fonctionnalités. J'en ai besoin en master pour entrer en production maintenant. Cela sauvera mes fesses.
Captain Hypertext

911

Utilisation

git cherry-pick <commit>

à appliquer <commit>à votre succursale actuelle .

Moi-même, je recouperais probablement les commits que je sélectionne gitket les sélectionne avec un clic droit sur l'entrée de validation à la place.


Si vous voulez aller plus automatiquement (avec tous ses dangers) et en supposant que toutes les validations depuis hier se sont produites sur wss, vous pouvez générer la liste des validations en utilisant git log(avec --prettysuggéré par Jefromi)

git log --reverse --since=yesterday --pretty=%H

donc tout ensemble en supposant que vous utilisez bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

Si quelque chose ne va pas ici (il y a beaucoup de potentiel), vous avez des problèmes car cela fonctionne sur la caisse en direct, alors faites des choix manuels ou utilisez un rebase comme suggéré par Jefromi.


Tous les espaces réservés pour l'option --pretty se trouvent dans la page de manuel git-log. Vous pouvez obtenir le format de votre choix - particulièrement utile pour obtenir les champs souhaités pour un script sous une forme facilement analysable.
Cascabel

Je voudrais également souligner que, en supposant que vous souhaitiez vraiment créer des validations en double, la méthode utilisée git rebasedans ma réponse est plus robuste. En particulier, en utilisant une boucle for comme celle-ci, si l'un des choix de cerise échoue, il essaiera toujours de faire tous les autres. C'est ... très très pas bon, disons.
Cascabel

2
D'accord. C'est pourquoi je ne l'utilise jamais, mais le fais manuellement. Mais la cerise sur le gâteau est toujours la réponse, du moins au titre de la question. J'ai modifié la réponse.
Benjamin Bannier

1
Quelqu'un s'est engagé dans une branche ancienne / incorrecte, et cherry-pick m'a laissé mettre ce commit dans la bonne branche (tout en le gardant comme committer). Parfait.
Patrick

8
Une vue rare, une gitréponse simple et directe à la solution, au lieu de parcourir les subtilités de git pour prouver à quel point le répondeur le sait.
Przemek D

74

git cherry-pick : Appliquer les modifications introduites par certaines validations existantes

Supposons que nous ayons la branche A avec (X, Y, Z) les commits. Nous devons ajouter ces commits à la branche B . Nous allons utiliser les cherry-pickopérations.

Lorsque nous utilisons cherry-pick, nous devons ajouter commits sur la branche B dans le même ordre chronologique que les commits apparaissent à la Direction A .

cherry-pick prend en charge une gamme de validations, mais si vous avez des validations de fusion dans cette gamme, cela devient vraiment compliqué

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

Exemple de workflow:

entrez la description de l'image ici

Nous pouvons utiliser cherry-pickavec des options

-e ou --edit : Avec cette option, git cherry-pick vous permettra de modifier le message de validation avant de valider.

-n ou --no-commit : Habituellement, la commande crée automatiquement une séquence de validations. Cet indicateur applique les modifications nécessaires pour sélectionner chaque validation nommée dans votre arborescence de travail et l'index, sans effectuer de validation. De plus, lorsque cette option est utilisée, votre index n'a pas besoin de correspondre à la validation HEAD. La sélection est effectuée par rapport à l'état de début de votre index.

Voici un article intéressant concernant cherry-pick.


19

Vous pouvez créer un correctif à partir des validations que vous souhaitez copier et appliquer le correctif à la branche de destination.


16
Même si, pour une raison quelconque, vous souhaitez vraiment utiliser des correctifs au lieu de choisir des cerises / rebaser, la manière la plus simple de le faire est avec git format-patch <revision range>et git am *.patch.
Cascabel

Il nécessite checkoutune autre branche.
CoolMind

12

Ou si vous êtes un peu moins du côté de l'évangéliste, vous pouvez faire un peu laid que j'utilise. Dans deploy_template, il y a des commits que je veux copier sur mon maître en tant que branche de déploiement

git branch deploy deploy_template
git checkout deploy
git rebase master

Cela créera une nouvelle branche de déploiement (j'utilise -f pour remplacer la branche de déploiement existante) sur deploy_template, puis rebasera cette nouvelle branche sur master, en laissant deploy_template inchangé.


1

Pour le cas simple de simplement copier le dernier commit de la branche wss vers v2.1, vous pouvez simplement récupérer l'id de commit ( git log --oneline | head -n 1) et faire:

git checkout v2.1
git merge <commit>

Cela nécessite de passer à une autre succursale.
CoolMind

1

La commande cherry-pick peut lire la liste des validations à partir de l'entrée standard.

La commande suivante cherry-picks valide les commits créés par l'utilisateur John qui existent dans la branche "develop" mais pas dans la branche "release", et le font dans l'ordre chronologique.

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.