web-dev-qa-db-fra.com

Hg: Comment faire une rebase comme celle de git

Dans Git, je peux faire ceci:

1. Commencez à travailler sur une nouvelle fonctionnalité: 
 $ Git co -b newfeature-123 # (une branche de développement d’entités locales) 
 Faire quelques commits (M, N, O) 
 
 maître A --- B --- C 
\
 nouveaut é-123 M --- N --- O 
 
 2. Extraire les nouvelles modifications du maître en amont: 
 $ Git pull 
 (Le maître est mis à jour avec ff-commits) 
 
 Maître A --- B --- C-- -D --- E --- F 
\
 Nouveaut é-123 M --- N --- O 
 
 3. Rebase off master afin que ma nouvelle fonctionnalité 
 Puisse être développée par rapport aux dernières modifications en amont: 
 (Extrait de newfeature-123) 
 $ Git rebase master 
 
 maître A --- B --- C --- D --- E --- F 
\
 nouveaut é-123 M --- N --- O 


Je veux savoir comment faire la même chose dans Mercurial, et j'ai parcouru le Web pour trouver une réponse, mais le mieux que j'ai pu trouver était: git rebase - can hg peut-il le faire

Ce lien fournit 2 exemples:
1. Je vais admettre que ceci: (en remplaçant les révisions de l'exemple par celles de mon propre exemple)

 hg up-F 
 hg branche -f newfeature-123 
 hg greffe -a -b newfeature-123 

n’est pas si mal que ça, sauf qu’elle laisse derrière elle la pré-base M-N-O en tant que tête non fusionnée et crée 3 nouveaux commits M ', N', O 'qui les représentent s’éloignant de la ligne principale mise à jour.

Fondamentalement, le problème est que je me retrouve avec ceci:

 maître A --- B --- C --- D --- E --- F 
\\ 
 nouveaut é-123\M '--- N' --- O '
\
 Nouveaut é-123 M --- N --- O 

ce n'est pas bon car cela laisse derrière nous des commits non désirés locaux qui doivent être abandonnés.

  1. L’autre option du même lien est
 hg qimport -r M: O 
 hg qpop -a 
 hg jusqu'à F 
 hg branche nouveaut é-123 
 hg qpush -a 
 hg qdel -r qbase: qtip 

et cela donne le graphe désiré:

 maître A --- B --- C --- D --- E --- F 
\
 nouveaut é-123 M --- N --- O 

mais ces commandes (toutes les 6!) semblent tellement plus compliquées que

 $ git rebase master 

Je veux savoir s’il s’agit du seul équivalent en Hg ou s’il existe un autre moyen aussi simple que Git.

207
jpswain

VonC a la réponse que vous cherchez , l'extension Rebase. Cela vaut cependant la peine de passer une seconde ou deux à réfléchir à la raison pour laquelle ni mq ni rebase ne sont activés par défaut dans Mercurial: parce que Mercurial est entièrement axé sur des changes indélébiles. Lorsque je travaille de la manière que vous décrivez, qui est presque quotidiennement, voici le schéma que je prends:

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

et c'est vraiment tout ce qui est nécessaire. Je me retrouve avec un clone newfeature-123 que je peux facilement. Retourner à la ligne principale lorsque j'en suis satisfait. Mais surtout, je n’ai jamais changé d’histoire . Quelqu'un peut consulter mes ensembles de jeux et voir à quoi ils ont été codés à l'origine et comment j'ai réagi aux modifications apportées à la ligne principale tout au long de mon travail. Tout le monde ne pense pas que cela ait de la valeur, mais je suis fermement convaincu que la tâche du contrôle de la source est de nous montrer non pas ce que nous espérions arriver, mais ce qui s'est réellement passé: chaque impasse et chaque refactor devraient laisser une trace indélébile et se rebaser. et d'autres techniques d'édition d'histoire cachent cela.

Maintenant, allez chercher la réponse de VonC pendant que je range ma caisse à savon. :)

233
Ry4an Brase

Vous pourriez être à la recherche de Rebase Extension . (implémenté dans le cadre du SummerOfCode 2008 )

Dans ces cas, il peut être utile de "détacher" les modifications locales, de synchroniser le référentiel avec le système principal, puis d'ajouter les modifications privées par-dessus les nouvelles modifications distantes. Cette opération s'appelle rebase.

Obtenir de :

alt text

à:

alt text


Comme commenté ci-dessous par steprobe :

Dans le cas où vous n'extrayez pas les modifications et que vous avez les deux branches dans votre référentiel, vous pouvez faire (en utilisant keepbranches):

hg up newfeature-123 
hg rebase -d master --keepbranches

(--keepbranches: Hérite du nom de la branche d'origine.)

Mojca mentionne:

J'aime utiliser hg rebase --source {L1's-sha} --dest {R2's-sha}, mais je ne savais pas que je pouvais ajouter --keepbranches à la fin.

Comme illustré ci-dessous par Jonathan Blackburn :

 hg rebase -d default --keepbranches
103
VonC

En supposant que vous ayez une installation Hg moderne, vous pouvez simplement ajouter:

[extensions]
rebase = 

à ~/.hgrc.

Ensuite, vous pouvez utiliser les commandes hg rebase, hg pull --rebase, ou hg help rebase.

44
sblom

Je ne pense pas que les réponses ci-dessus atteignent l'objectif du PO, qui était de conserver sa branche de tâche, mais simplement de se baser sur un point ultérieur de la branche parente.

Supposons que je commence par ce graphique (généré à l'aide de l'extension graphlog. Amour sérieux du geek pour graphlog).

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

Si je suis sur la branche feature3 et que je veux le rebaser du commit à nouveau, je comprends que je lancerais hg rebase -d default. Cela a le résultat suivant:

@  89dada24591e Feature 3 commit 2 tip 
|
o  77dcce88786d Feature 3 branch commit 1  
|
o  af630ccb4a80 default againagainagain  
|
o  e9f850ac41da foo  

Mission accomplie? Je ne pense pas. Le problème est que lorsque les commits sur la branche feature3 ont été à nouveau basés sur une nouvelle base, la branche feature3 a été supprimée. Mes commits ont été déplacés vers la branche par défaut, ce que j’essayais d’éviter.

Sous Git, le résultat ressemblerait à ceci:

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

Notez que la branche feature3 existe toujours, les deux commits sont toujours sur la branche feature3 et ne sont pas visibles par défaut. Sans préserver la branche de tâche, je ne vois pas en quoi cette fonction est différente de la fusion.

UPDATE : J'ai découvert le --keepbranches drapeau supporté par hg rebase, et je suis heureux de signaler que tout va bien. En utilisant hg rebase -d default --keepbranches, Je reproduis exactement le comportement Git dont j'avais envie. Quelques pseudonymes plus tard et je me rebase comme si personne ne le faisait.

21
Jonathan Blackburn

Puisque certaines personnes ont dit qu'elles pensaient qu'il était bon de conserver chaque itération de tout, je ferai remarquer que, pour les projets open source plus vastes, accepter les modifications pleines de fusions et d'itérations de développement créerait un historique de révision désordonné, et l'historique de révision est moins utile pour voir comment la version actuelle est arrivée là.

Cela fonctionne bien lorsque les modifications soumises sont examinées par des personnes qui ne les ont pas écrites, avant leur acceptation. Les modifications qui entrent dans la ligne principale sont généralement déboguées et fonctionnelles. Ensuite, lorsque vous revenez sur l'origine d'une ligne, vous voyez tous les changements qui vont avec, pas un point au milieu du développement du changement dont il fait partie.

La page x265 contributors explique comment réengager une série de modifications sur lesquelles vous travaillez, afin de les préparer pour la soumission au projet x265. (Y compris l'utilisation de TortoiseHG pour valider certaines modifications mais pas toutes dans un fichier individuel, comme le fragment de scène de git gui pour un commit).

Le processus consiste à mettre à jour hg avec le conseil en amont, puis à obtenir toutes vos modifications non validées dans le répertoire de travail. Indiquez tout ce qui ne fait pas partie de ce que vous voulez soumettre, puis divisez le reste en autant de commits séparés, avec les messages Nice commit.

J'imagine que vous copiez/collez puis modifiez les messages de validation des itérations précédentes d'un ensemble de correctifs que vous révisez. Ou peut-être pourriez-vous greffer vos anciens commits (choisissez dans le langage git), puis modifiez-les un par un pour obtenir vos anciens messages de commissions comme point de départ pour l'édition.

3
Peter Cordes