Comment fermer correctement une branche de fonctionnalité dans Mercurial?

240

J'ai fini de travailler sur une branche de fonctionnalité feature-x. Je veux fusionner les résultats dans la defaultbranche et fermer feature-xafin de m'en débarrasser dans la sortie de hg branches.

J'ai trouvé le scénario suivant, mais il a quelques problèmes:

$ hg up default
$ hg merge feature-x
$ hg ci -m merge
$ hg up feature-x
$ hg ci -m 'Closed branch feature-x' --close-branch

Ainsi, la feature-xbranche (modifications 40- 41) est fermée, mais il y a une nouvelle tête , le changement de branche de fermeture 44, qui sera répertorié à hg headschaque fois:

$ hg log ...
o  44 Closed branch feature-x
|
| @  43 merge
|/|
| o  42 Changeset C
| |
o |  41 Changeset 2
| |
o |  40 Changeset 1
|/
o  39 Changeset B
|
o  38 Changeset A
|

Mise à jour : Il semble que depuis la version 1.5 Mercurial ne montre plus les têtes de branches fermées dans la sortie de hg heads.

Est-il possible de fermer une branche fusionnée sans laisser une tête de plus? Existe-t-il un moyen plus correct de fermer une branche de fonctionnalité?

Questions connexes:

Andrey Vlasovskikh
la source
@Andrey: mais l'article souligné ne parle PAS seulement de "--close-branch". Il montre quatre façons de tailler votre branche. Si vous n'en voulez vraiment plus, vous pouvez cloner comme expliqué dans l'article. Le seul «problème» est si, pour une raison quelconque, vous souhaitez le fermer, mais le garder autour.
SyntaxT3rr0r
1
@WizardOfOdds Oui, j'ai lu tout l'article sur l'élagage des branches mortes. Je veux que la branche reste dans l'historique des révisions, pas pour la jeter. Auparavant, je fusionnais simplement les branches de fonctionnalités defaultsans les "fermer". Il en est résulté 0 nouvelles têtes mais de telles branches étaient visibles pour hg branchestoujours (sous forme de branches inactives).
Andrey Vlasovskikh
Pour développer des fonctionnalités, j'ai tendance à cloner l'ensemble du référentiel, puis à le fusionner une fois la fonctionnalité terminée. Je n'aime pas avoir les restes de branches (fermées) dans l'histoire.
DanMan

Réponses:

218

Une façon consiste simplement à laisser les branches de fonctionnalités fusionnées ouvertes (et inactives):

$ hg up default
$ hg merge feature-x
$ hg ci -m merge

$ hg heads
    (1 head)

$ hg branches
default    43:...
feature-x  41:...
    (2 branches)

$ hg branches -a
default    43:...
    (1 branch)

Une autre façon consiste à fermer une branche de fonctionnalité avant de fusionner à l'aide d'un commit supplémentaire:

$ hg up feature-x
$ hg ci -m 'Closed branch feature-x' --close-branch
$ hg up default
$ hg merge feature-x
$ hg ci -m merge

$ hg heads
    (1 head)

$ hg branches
default    43:...
    (1 branch)

Le premier est plus simple, mais il laisse une branche ouverte. La seconde ne laisse aucune tête / branche ouverte, mais elle nécessite un commit auxiliaire supplémentaire. On peut combiner le dernier commit réel à la branche de fonctionnalité avec ce commit supplémentaire en utilisant --close-branch, mais il faut savoir à l'avance quel commit sera le dernier.

Mise à jour : Depuis Mercurial 1.5 , vous pouvez fermer la branche à tout moment afin de ne pas apparaître dans les deux hg brancheset hg headsplus. La seule chose qui pourrait éventuellement vous ennuyer est que techniquement le graphique de révision aura toujours une révision de plus sans childen.

Mise à jour 2 : depuis Mercurial 1.8, les signets sont devenus une fonctionnalité centrale de Mercurial. Les signets sont plus pratiques pour la création de branches que les branches nommées. Voir aussi cette question:

Andrey Vlasovskikh
la source
2
Ce n'est pas nécessairement vrai Bookmarks are more convenient for branching than named branches. Les signets Hg ne sont pas la même chose que les branches Git. Ils sont pleins de nombreux cas de bord qui les rendent inappropriés comme branches de fonctionnalité. Par exemple: lorsque vous clonez un référentiel, vous vous retrouvez avec le dernier commit de la defaultbranche. Si vous utilisez des signets, cet ensemble de modifications correspond à un signet aléatoire (instable). Si vous utilisez des branches nommées, vous obtiendrez le dernier commit dans la branche stable / par défaut, qui est généralement ce que vous voulez. Les signets y arriveront un jour, mais ils ne sont pas encore là.
Gili
J'utilise des signets comme balises privées qui ne sont visibles que dans mon référentiel local. Ils rappellent les changements que je dois revoir.
Gili
J'ai essayé de suivre cette approche, mais je reçois encore une erreur en essayant de pousser: abort: push creates new remote branches:. Qu'est-ce que j'aurais pu faire de mal?
kasperd
79

à mon humble avis, il y a deux cas pour les branches qui ont été oubliés de fermer

Cas 1: la branche n'a pas été fusionnée avec la valeur par défaut

dans ce cas, je mets à jour la branche et fais un autre commit avec --close-branch, malheureusement, cela choisit la branche pour devenir la nouvelle astuce et donc avant de la pousser vers d'autres clones, je m'assure que la vraie astuce reçoit encore plus de changements et d'autres ne vous trompez pas sur cette étrange astuce.

hg up myBranch
hg commit --close-branch

Cas 2: la branche a été fusionnée en défaut

Ce cas n'est pas très différent du cas 1 et il peut être résolu en reproduisant les étapes du cas 1 et deux étapes supplémentaires.

dans ce cas, je mets à jour l'ensemble de modifications de branche, fais un autre commit avec --close-branch et fusionne le nouvel ensemble de modifications qui est devenu la pointe par défaut. la dernière opération crée une nouvelle astuce qui se trouve dans la branche par défaut - HOORAY!

hg up myBranch
hg commit --close-branch
hg up default
hg merge myBranch

J'espère que cela aidera les futurs lecteurs.

Nachbars Lumpi
la source
3
Bonne réponse claire pour un débutant Mercurial comme moi. Et merci de ne pas utiliser "ci" qui n'est pas répertorié comme l'une des commandes par hg help, donc je ne sais pas ce que cela signifie :)
MB.
8
@MB .: dans de tels cas, vous hg help cil'expliquera.
Chris Morgan
Je crois que la commande «hg merge» vous le dira, il y a encore un autre commit à la fin
Chip Grandits
11

EDIT aïe, trop tard ... Je sais que vous avez lu votre commentaire indiquant que vous souhaitez conserver le jeu de modifications Feature-X, donc l'approche de clonage ici ne fonctionne pas.

Je laisserai toujours la réponse ici car cela pourrait aider les autres.

Si vous voulez vous débarrasser complètement de la "fonctionnalité X", parce que, par exemple, cela n'a pas fonctionné, vous pouvez cloner. C'est l'une des méthodes expliquées dans l'article et elle fonctionne, et elle parle spécifiquement des têtes.

Pour autant que je sache, vous avez cela et que vous voulez vous débarrasser de la tête "feature-x" une fois pour toutes:

@    changeset:   7:00a7f69c8335
|\   tag:         tip
| |  parent:      4:31b6f976956b
| |  parent:      2:0a834fa43688
| |  summary:     merge
| |
| | o  changeset:   5:013a3e954cfd
| |/   summary:     Closed branch feature-x
| |
| o  changeset:   4:31b6f976956b
| |  summary:     Changeset2
| |
| o  changeset:   3:5cb34be9e777
| |  parent:      1:1cc843e7f4b5
| |  summary:     Changeset 1
| |
o |  changeset:   2:0a834fa43688
|/   summary:     Changeset C
|
o  changeset:   1:1cc843e7f4b5
|  summary:     Changeset B
|
o  changeset:   0:a9afb25eaede
   summary:     Changeset A

Vous faites donc ceci:

hg clone . ../cleanedrepo --rev 7

Et vous aurez ce qui suit, et vous verrez que la fonction-x a bel et bien disparu:

@    changeset:   5:00a7f69c8335
|\   tag:         tip
| |  parent:      4:31b6f976956b
| |  parent:      2:0a834fa43688
| |  summary:     merge
| |
| o  changeset:   4:31b6f976956b
| |  summary:     Changeset2
| |
| o  changeset:   3:5cb34be9e777
| |  parent:      1:1cc843e7f4b5
| |  summary:     Changeset 1
| |
o |  changeset:   2:0a834fa43688
|/   summary:     Changeset C
|
o  changeset:   1:1cc843e7f4b5
|  summary:     Changeset B
|
o  changeset:   0:a9afb25eaede
   summary:     Changeset A

J'ai peut-être mal compris ce que vous vouliez, mais ne modifiez pas, j'ai pris le temps de reproduire votre cas d'utilisation:)

SyntaxeT3rr0r
la source
7

Il est étrange que personne n'ait encore suggéré la manière la plus robuste de fermer une branche de fonctionnalités ... Vous pouvez simplement combiner la validation de fusion avec le drapeau --close-branch (c'est-à-dire valider les fichiers modifiés et fermer la branche simultanément):

hg up feature-x
hg merge default
hg ci -m "Merge feature-x and close branch" --close-branch
hg branch default -f

Voilà, c'est tout. Aucune tête supplémentaire sur revgraph. Aucun engagement supplémentaire.

tav
la source
Je l'ai mentionné dans ma réponse: "" "On peut combiner le dernier commit réel à la branche de fonctionnalité avec ce commit supplémentaire en utilisant --close-branch, mais il faut savoir à l'avance quel commit sera le dernier." " "
Andrey Vlasovskikh
OK je vois. Je ne comprends tout simplement pas la dernière partie de la phrase ("mais il faut savoir ..."), alors j'ai pensé que cela signifiait quelque chose de différent. Je voudrais également noter que cette méthode n'est pas prise en charge par la plupart des outils GUI (TortoiseHG, SourceTree, etc.).
TAV
@AndreyVlasovskikh Le but de cette réponse est de fermer la branche dans la fusion plutôt que dans le dernier commit de la branche de fonctionnalité.
kasperd
@tav Avant d'émettre la mergecommande, il peut être judicieux hg branchde vérifier que le nom de branche de la fusion est bien celui que vous souhaitez conserver ouvert.
kasperd
2
À y regarder de plus près, il semble que la fusion se fera toujours sur la branche fermée. Le résultat souhaité serait qu'il se trouve sur la branche de l'un de ses parents et ferme la branche de son autre parent. Cela ne semble pas possible. Cela ne ressemble donc pas à une solution viable après tout. Dommage, je voulais vraiment utiliser une fusion comme point de fermeture d'une branche.
kasperd