Avec Mercurial, comment puis-je «compresser» une série de changesets en un seul avant de pousser?

96

Disons que j'ai un référentiel Mercurial local et distant. Maintenant, je commence à travailler sur une fonctionnalité. Je travaille dessus, et quand je pense que c'est fait, je valide le changeset. En le testant un peu plus, je trouve que je pourrais encore améliorer cette fonctionnalité en modifiant quelque chose dans le code. Je fais le changement et je m'engage. 20 minutes plus tard, je trouve qu'il y a un bogue dans cette nouvelle fonctionnalité, donc je le corrige et je le valide aussi.

J'ai maintenant 3 changesets que j'aimerais vraiment pousser vers le référentiel distant comme un changeset avec le message "Implementing feature X", par exemple.

Comment puis-je faire cela sans trop de tracas? Je pense que je pourrais le faire avec des correctifs, mais cela semble demander beaucoup de travail.

Lucas
la source
40
De toute évidence, ce n'est pas à moi de vous dissuader d'essayer de compresser vos ensembles de modifications, mais vous voudrez peut-être considérer que la moitié de la valeur du contrôle de version est de répondre «pourquoi» pas seulement «quoi» des mois et des années plus tard. Une représentation précise de la façon dont une fonctionnalité est apparue, et à quelles étapes, pourrait avoir une valeur future. Le rejeter semble tellement ... sans contrôle.
Ry4an Brase
Cela conduit à une autre question ... Quelle est la différence entre 'histedit' et 'collapse'
sylvanaar
1
collapse fournit un sous-ensemble des fonctionnalités de histedit, et histedit a une UX beaucoup plus intuitive.
Stefan Rusek
1
Il fournit également un mécanisme pour modifier le message d'ensemble de modifications fusionné.
Stefan Rusek
1
@ Ry4an: En fait, l'écrasement / la réduction ajoute de la pertinence au contrôle de version dans certains cas. Sans écraser, j'aurais deux commits chaque jour qui n'ont rien à voir avec des fonctionnalités ou des corrections de bogues, mais qui sont pour déplacer le code de l'ordinateur portable vers le bureau et vice versa. Ils ajoutent simplement du bruit à l'historique des versions.
John Reynolds

Réponses:

39

Qu'en est-il de l' extension de réduction ?

Steve Losh
la source
20
Salutations du futur! Je viens de rechercher les mêmes fonctionnalités sur Google et, apparemment, de nos jours, hg prend en charge cela dès la sortie de la boîte hg rebase --collapse. Consultez le wiki hg sur la commande rebase. Étant donné que cette question est le troisième résultat de la recherche globale et le premier sur stackoverflow, j'ai pensé que ces informations pourraient être utiles.
a.peganz
1
Salutations encore plus loin dans le futur !! L'extension rebase semble être uniquement destinée à déplacer les ensembles de modifications d'une branche à une autre. Oui, il existe une option --collapse, mais elle semble toujours être applicable uniquement lors du déplacement d'un ensemble de modifications entre les branches. Voir < mercurial-scm.org/wiki/... >
Brad Oestreicher
3
Vous pouvez utiliser hg rebaseavec --collapsedans une seule branche.
UuDdLrLrSs
52

L' extension histedit est exactement ce que vous recherchez.

hg histedit -o

ou

hg histedit --outgoing

affichera une liste des changesets sortants. À partir de la liste, vous pouvez

  • Pliez au moins 2 ensembles de modifications en créant un seul ensemble de modifications
  • Supprimer les ensembles de modifications en les supprimant de l'historique
  • Réorganisez les ensembles de modifications comme vous le souhaitez.

histedit vous demandera le nouveau message de validation des ensembles de modifications pliés qui par défaut les deux messages avec "\ n *** \ n" les séparant.

Vous pouvez également obtenir des résultats similaires en utilisant l'extension mq, mais c'est beaucoup plus difficile.

Vous pouvez également utiliser l'extension de réduction pour simplement faire un pliage, mais elle ne fournit pas une interface utilisateur aussi agréable et ne permet pas de modifier le message de validation résultant. La modification du message de validation résultant permet également de nettoyer le message final, ce que je finis toujours par utiliser.

Stefan Rusek
la source
merci, c'est exactement ce dont j'avais besoin. Ce serait bien si vous pouviez le faire depuis TortoiseHg - mais la ligne de commande est assez simple.
sylvanaar
21

Oui, vous pouvez le faire avec des correctifs: supposons que votre travail se trouve dans les ensembles de modifications 100 à 110 inclus

  1. Créez un patch:

    % hg export -o mypatch 100:110 --git

  2. Mettre à jour à 99:

    % hg update 99

  3. Appliquez le patch avec --no-commit (sinon vous récupérerez tous vos ensembles de modifications):

    % hg import --no-commit mypatch

  4. Validez toutes les modifications en même temps:

    % hg commit

  5. Vous avez maintenant deux têtes (110 et 111) qui devraient être équivalentes en termes de fichiers qu'elles produisent dans votre répertoire de travail - peut-être les diffèrent pour raison avant de supprimer les anciennes:

    % hg strip 100

OK, maintenant que j'ai tout expliqué, cela semble long, mais après l'avoir fait plusieurs fois moi-même, je ne trouve pas que ce soit trop une corvée ...

Arkady
la source
1
Excellente réponse, mais il y a une condition préalable: l' extension MQ doit être activée .
Chris Kelly
Pour inclure également les modifications dans les fichiers binaires, assurez-vous d'utiliser l'option --git: par exemple: "hg export -o mypatch 100: 110 --git" Pour plus d'informations, veuillez consulter: stackoverflow.com/a/12537738/ 367663 J'ai pris la liberté de modifier la réponse.
Kharlos Dominguez
1
Semble trop compliqué, pourquoi pas hg strip --keepet puis commet tout dans un seul commit?
G.Demecki
@ G.Demecki Parce que c'est une opération potentiellement très avec pertes ..? Bien que MQ soit excessif (et même souvent déconseillé), sauf lorsque vous souhaitez un tel flux de travail.
user2864740
@ user2864740 Vous avez peut-être raison, car je ne suis pas un expert Mercurial. Mais par défaut, hg stripplacera une sauvegarde dans le .hg/strip-backup/répertoire. Je suppose que ce n'est pas aussi sûr que cela, git reflogmais fournit quand même une sorte de sauvetage.
G.Demecki
19

Si vous utilisez TortoiseHg, utilisez peut simplement sélectionner deux révisions (utilisez CTRL pour sélectionner les non-suivantes), faites un clic droit et sélectionnez "Compresser l'historique" .

Après cela, vous obtiendrez une nouvelle liste de modifications dans la nouvelle tête à partir du premier changement que vous avez sélectionné auparavant, elle contiendra toutes les listes de modifications descendantes entre celles que vous avez sélectionnées.

Vous pouvez simplement supprimer les anciennes listes de modifications si vous n'en avez plus besoin: utilisez les extensions MQ pour cela. Encore une fois, dans TortoiseHg: faites un clic droit sur la première liste de modifications qui doit être supprimée avec tous ses descendants, "Modifier l'historique -> Supprimer" .

George Marian
la source
18

Ma méthode préférée d'utilisation de mq pour ce pliage est d'utiliser TortoiseHg comme décrit ici . Cependant, cela peut facilement être fait à partir de la ligne de commande comme ceci:

hg qimport -r <first>:<last> 
    -- where <first> and <last> are the first and last changesets 
    -- in the range of revisions you want to collapse

hg qpop <first>.diff
    -- remove all except for the first patch from the queue
    -- note: mq names patches <#>.diff when it imports them, so we're using that here

hg qfold <next>.diff
    -- where <next> is <first>+1, then <first>+2, until you've reached <last>

hg qfinish -a
    -- apply the folded changeset back into the repository

(Il peut y avoir une meilleure façon de faire l'étape qfold, mais je ne suis pas au courant, car j'utilise habituellement TortoiseHg pour cette opération.)

Cela semble un peu compliqué au début, mais une fois que vous avez commencé à utiliser mq, c'est assez simple et naturel - en plus vous pouvez faire toutes sortes d'autres choses avec mq qui peuvent être très pratiques!

Chris Phillips
la source
4

hg collapseet hg histeditsont les meilleurs moyens. Ou, plutôt, ce serait la meilleure façon, s'ils fonctionnaient de manière fiable ... Je suis arrivé histedità planter avec un vidage de pile en trois minutes. Collapsen'est pas tellement mieux.

J'ai pensé que je pourrais partager deux autres BKM:

  1. hg rebase --collapse

    Cette extension est distribuée avec Mercurial. Je n'ai pas encore eu de problèmes avec ça. Vous devrez peut-être jouer à certains jeux pour contourner les hg rebaselimitations - en gros, cela n'aime pas le rebasage vers un ancêtre sur la même branche, nommée ou par défaut, bien qu'il le permette en cas de rebasage entre des branches (nommées).

  2. Déplacez le référentiel ( foo/.hg) vers le répertoire de travail ( bar) et ses fichiers. Pas l'inverse.

Certaines personnes ont parlé de créer deux arborescences clones et de copier des fichiers entre elles. Ou patcher entre eux. Au lieu de cela, il est plus facile de déplacer les .hgrépertoires.

hg clone project work
... lots of edits
... hg pull, merge, resolve
hg clone project, clean
mv work/.hg .hg.work
mv clean/.hg work/.hg
cd work
... if necessary, pull, nerge, reconcile - but that would only happen because of a race
hg push

Cela fonctionne tant que les vrais référentiels, les .hgarborescences, sont indépendants du répertoire de travail et de ses fichiers.

S'ils ne sont pas indépendants ...

Krazy Glew
la source
En 2015, histeditc'est une très bonne option pour cette tâche. Je ne lui fais toujours pas confiance car je fais un git rebase -i, mais il ne plante pas .. au moins les versions plus récentes vous laisseront sur une branche temporaire si quelque chose va horriblement mal donc la seule fois où les ensembles de modifications seront supprimés est après la validation de la nouvelle branche.
user2864740
2

Je n'ai jamais utilisé Mercurial, mais cela ressemble beaucoup à ce dont parlait Martin Fowler sur son blog il n'y a pas si longtemps:

http://martinfowler.com/bliki/MercurialSquashCommit.html

Joseph
la source
Cela semble plus qu'un peu compliqué, mais merci pour le lien. Honnêtement, j'espère une extension magique qui fera exactement ce que je veux, comme la récupération et la transplantation avec les changsets de traction et de sélection de cerises.
Lucas
0

Pourquoi ne pas simplement hg strip --keepcommander?

Ensuite, vous pouvez valider toutes les modifications en un seul commit.

G. Demecki
la source
@Strawberry ne fournit pas de réponse ?? Il pense que cela répond parfaitement à la question de l'auteur. Pouvez-vous préciser votre point?
G.Demecki
C'est de l'histoire ancienne, je vais donc retirer la remarque - mais la réponse approuvée semble être une référence plus faisant autorité.
Fraise du
1
@Strawberry En effet, c'est un fil ancien. Mais la réponse acceptée est obsolète, car Mercurial n'a plus besoin d'une extension tierce distincte pour ce travail.
G.Demecki
0

HistEdit fera ce que vous voulez, mais c'est probablement exagéré. Si la seule chose dont vous avez besoin est de plier certains ensembles de modifications ensemble, l' extension de réduction fera l'affaire.

Steve Losh
la source
1
bien qu'il fournisse une interface utilisateur beaucoup plus facile à utiliser et à comprendre, ce qui est une raison plus que suffisante pour l'utiliser, mais il fournit également un mécanisme pour modifier le message de l'ensemble de modifications fusionné, ce qui est une autre chose que je veux toujours faire lorsque je fusionner les ensembles de modifications.
Stefan Rusek
Et le problème de ne comprendre que l'interface utilisateur est que l'on ne comprend vraiment pas. Quoi qu'il en soit, pour le passé, alors que histedit permet de changer les «messages», ainsi que de changer les messages lors du «pliage». L'histedit est parfait; si quoi que ce soit, l'extension d'effondrement est peu utile.
user2864740
0

Supposons que vous ayez deux validations THISet non publiées THATdans Mercurial et que vous souhaitiez qu'elles se joignent en une seule validation au THISpoint ::

... --> THIS --> ... --> THAT --> ... --> LAST

Vérifiez que vos commits ne sont pas publiés:

$ hg glog -r "draft() & ($THIS | $THAT)"

Mettre à jour pour LASTcommettre:

$ hg up

et import commits jusqu'à THISdans MQ ::

$ hg qimport $THIS::.

Désappliquez tous les correctifs et appliquez seulement en premier THIS:

$ hg qpop -a
$ hg qpush
$ hg qapplied
... THIS ...

Rejoignez THAT:

$ hg qfold $THATNAME

REMARQUE Pour trouver le nom, THATNAMEutilisez:

$ hg qseries

Appliquez tous les correctifs et déplacez-les vers l'historique du référentiel:

$ hg qpush -a
$ hg qfinish -a

Mon article de blog sur le sujet rejoint deux commits dans Mercurial .

gavenkoa
la source
0

Oui, strip --keepfonctionne pour la question de l'auteur. Mais c'était légèrement différent des autres, par exemple, si vous avez la version 1 à 30 mais que vous voulez seulement réduire la version 12-15. D'autres solutions fonctionnent mais pas strip --keep.

Frank Tao
la source