Size: 8234
Comment:
|
Size: 6650
Comment: added data about behavior regarding branch name.
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
#pragma section-numbers 2 |
|
Line 3: | Line 5: |
A plan for light weight branching/categorization what would work with other Mercurial principle and actual DVCS idea. | = Topic Plan = |
Line 5: | Line 7: |
Still a very early prototype stage. | A (speculative) plan for topic branching that would work more seamlessly with common Mercurial workflows. Still very early prototype stage. Everything is subject to change. |
Line 9: | Line 11: |
== Background == | == Problem Statement == |
Line 11: | Line 13: |
Mercurial have been struggling for year to define a nice way to handle 'topic' branch (also called 'feature' branch) especially when it come to exchange them with other people (eg: for pull request). | The Mercurial community has been struggling for years to define a nice way to handle 'topic' branches (sometimes also called 'feature' branches), especially when it comes to sharing them with other people (mainly for code review or other collaboration.) |
Line 13: | Line 15: |
=== Constraint === | Bookmarks are a clone of git's refs, which seems to work more poorly in Mercurial than they do in Git, in part because the synchronization parts of bookmarks aren't really done. Adding the remaining bits of git's refs to Mercurial has been controversial, and may represent enough of a behavior change that it's infeasible. |
Line 15: | Line 17: |
The main challenges to get such feature right are: | Named branches are visible forever in the revision history, which makes them unsuitable for feature branch work as the feature branch names rapidly pollute the output of things like `hg branches`. |
Line 17: | Line 19: |
- '''Life cycle''': grouping/naming the topic branch is usually only relevant while working to get the feature done. We need a natural/efficient way for the topic to fade away when feature are complete. |
== Current Target == |
Line 20: | Line 21: |
- '''Distributed system''': Mercurial let arbitrary number of changesets to interact with each other the way they want, include pulling changesets through a chain or repository. A good solution for topic branch should work well in such distributed environment. So topic information must be exchanged at the same time as the commit they are attached to. |
This describe the target semantic and behavior for topics. |
Line 23: | Line 23: |
- '''Tracking/Target''': People make changes with the goal to get them integrated into a main line of development (default, stable, version 4.2, stagging, etc). This "target" should be the default destination for merge, rebase, update (and any other command it make sense?). This aspect can probably use (or maybe need) integration with the life cycle. |
=== General semantics === |
Line 26: | Line 25: |
- '''Clearly defined set of changes''': A topic is usually composed of multiple changesets, being able to easily define what is in the set is important for commands that handle topic as a whole (eg histedit, prev, next) and probably a very important point to design UI around evolve. Having a defined set of changesets is also needed when only part of the topic is exchanged (pushed or pulled). Topic cannot cannot just be defined from topological branch because rebasing a topic on the main branch makes such topological branch disappear (and also, topic may be multi headed or some topic share some common part of a branch). |
TL;DR; topic are an extra "light-branch" data relevant to draft changesets. |
Line 29: | Line 27: |
- '''Anonymous branching''': Anonymous branch (and others graph property) is a useful feature of mercurial that adds flexibility and improve productivity. We should keep this strength available within each topic. |
* Topic is a ''name'' explicitly attached to changesets, |
Line 32: | Line 29: |
- '''name conflict handling''': Fixing a bad name (or people fighting over a name) should not result in too complicated situation. |
* This Topic data is primarily meant to categorize ''draft changeset'' and fade out when things become public, |
Line 35: | Line 31: |
=== Current short coming of bookmarks === | * Changeset have both a ''topic'' and a 'branch'. The ''topic'' allow to gather related in progress work, while the ''branch'' data refer to the long terms line of development. |
Line 37: | Line 33: |
This section (and page) is not meant as "bookmark are doomed, lets do something else. The idea here is "we have long standing issue with bookmark, lets think again from scratch a see what emerge. We'll see what to do with the other idea after. | * Behaviors focus on ensuring any ''name'' have a single head. |
Line 39: | Line 35: |
There is currently an experimentation around the idea of "remote bookmarks" and wider work flow changes, it will be "evaluated" independently. (its a wiki Feel free to update content of this section) | * Behaviors related to named branches behave mostly as if the draft-with topic are not on the branch (yet). |
Line 41: | Line 37: |
||requirements || in-core || remote || ||Life cycle || poor || poor || ||distributed || okay || bad || ||tracking || || good || ||defined set || poor || poor || ||partial exch || bad || poor || ||branching || bad || bad || ||conflict || okay || good || |
* Behaviors within a topic are similar (with minor sensible difference) to named branches one within the topic. |
Line 50: | Line 39: |
=== General effect on named branch === | |
Line 51: | Line 41: |
'''Life cycle''' of bookmark are problematic because we still have not figured out a proper way to handle deletion and renaming. So once they are in the wild, it is very hard to get ride of a feature related bookmark. Not sure if remote-bookmarks improve that a bit. | Changeset with topic are ''only aspiring'' to be part of the named branch, but not fully in that branch yet. when you have branch `foo` name `foo` is resolved to the heads of `foo` with no topic. |
Line 53: | Line 43: |
Behavior in '''distributed''' is okay-ish for the in-core bookmark. The current behavior on pull work in a distributed ways as it will exchange any bookmark alongside their changeset. However behavior on push is more problematic as local bookmark may not be pushed, and Mercurial may warn about it or not depending unrelated condition. The 'remote-boomarks' change is more problematic in this aspect as remote name are not propagated so changesets can get exchanged without there topic information. | Three is a couple of examples: |
Line 55: | Line 45: |
'''tracking''' is not covered at all by current core version. It is introduced with 'remote-bookmark' but only cover rebase, the UI to setup and observe tracking is unclear to me yet. | {{{#!dot digraph { rankdir=LR node [shape=box,style=filled] A -> B -> C; B -> X -> Y; A [label="A\n(b: foo)"]; B [label="B\n(b: foo)"]; C [label="C\n(b: foo)"]; X [label="X\n(b: foo)\n(t: bar)",fillcolor="lightblue"]; Y [label="Y\n(b: foo)\n(t: bar)",fillcolor="lightblue"]; } }}} |
Line 57: | Line 59: |
A bookmark can implicitly '''define a set of revision''' since everything 'only' under that bookmark it can be considered in the topic. This have issue with: | Multiple heads are not longer ambiguous, |
Line 59: | Line 61: |
* Requires the use of bookmarks for the main branches too. * Misbehave if a some part of the topic is shared with another bookmark (or anon heads) * Bad handling of extra anonymous heads on the same topic. * ill defined behavior when push only half of a topic (who does not hold the bookmark) |
* The name `foo` resolve to C, * The name `bar` resolve to Y, |
Line 64: | Line 64: |
Because they refer to a single changeset at the top of the stack, bookmark are bad at '''partial exchange'''. It is often practical to push or to pull only a part of the topic because the rest is not ready yet. Because the bookmark have no "start" the changesets are pulled anonymously in this case. | ---- |
Line 66: | Line 66: |
For the same reason (refer to a single things) bookmark are does not allow for experimental branch and small popping heads in the same topics. | {{{#!dot digraph { rankdir=LR node [shape=box,style=filled] A -> B; B -> X -> Y; A [label="A\n(b: foo)"]; B [label="B\n(b: foo)"]; X [label="X\n(b: foo)\n(t: bar)",fillcolor="lightblue"]; Y [label="Y\n(b: foo)\n(t: bar)",fillcolor="lightblue"]; } }}} |
Line 68: | Line 79: |
Beside the current state of their implementation, divergent bookmarks provide a solution for ''conflict'''. however it does not handle recessing a bookmark or deletion/recreation cycle, but this is more related to live cycle. | Partial data does not have radical change on the definition, |
Line 70: | Line 81: |
== Open idea == | * The name `foo` resolve to B, * The name `var` resolve to Y, |
Line 72: | Line 84: |
This is a list of idea that emerged while brain storming. | ---- |
Line 74: | Line 86: |
* Topic could be a property attached to each changesets (grouping them by similar topic) | {{{#!dot digraph { rankdir=LR node [shape=box,style=filled] A -> X -> B; A [label="A\n(b: foo)"]; X [label="X\n(b: foo)\n(t: bar)",fillcolor="lightblue"]; B [label="B\n(b: foo)"]; } }}} |
Line 76: | Line 97: |
* Topic could fade away when changesets become public (either, archived or plain dropped) | Usual traversal rules apply: * The name `foo` resolve to B, * The name `var` resolve to X, === Behavior for update === This implies change in hg update behavior (but are not super relevant) === Behavior for merge === This assume `hg rebase` and `hg merge` to be identical === Behavior for push to publishing (default repo) === === Behavior for push to non-publisehd repo === === Stacked diffs workflow === === User Transition === == Pro and Cons == == Other questions == == Open ideas == This is a list of idea that emerged while brainstorming. This served as base for the current things. * Topic could be a property attached to each changeset (grouping them by similar topic) * Topic could fade away when changesets become public (either archived or plain dropped) * A benefit of archiving them is that users can query for topics, eg you could say `hg log -r topic(issue123)` which would help |
Line 84: | Line 137: |
* Topic could be non contiguous ([[mpm]] idea) feature-foo -> fix-bar -> feature-foo. Allowing a stream lined work that is automatically split apart after that. | * Topics could be non contiguous ([[mpm]] idea) feature-foo -> fix-bar -> feature-foo. Allowing a streamlined work that is automatically split apart after that. |
Line 86: | Line 139: |
* Topic could be hierarchical 'issue4700.test' 'issue4700.preparation', activation//reference could be done at any level 'issue4700' or 'issue4700' (this could help handle branching/different approach) | * Topics could be hierarchical 'issue4700.test' 'issue4700.preparation', activation//reference could be done at any level 'issue4700' or 'issue4700' (this could help handle branching/different approach) |
Line 88: | Line 141: |
* pushing a new head on a new topic to a '''non publishing server''' would be allowed. | * pushing a new head on a new topic to a '''non-publishing server''' would be allowed. * that is, it'd be legal to have one head per topic on a non-publishing server. |
Line 91: | Line 145: |
* Augie doesn't feel great about this option just because of UI complexity. | |
Line 92: | Line 147: |
== principle of very primitive extension == | * Users can name patches (in a sense) without mq * One of the major complaints about evolve from veteran mq users is that their patches no longer have explicit names. Topics provide a potential way to name patches again. |
Line 94: | Line 150: |
Assign topics to non-public changesets. A topic is like a named branch, in that it is a label on a changeset (the initial prototype even stores the topic in the extra area in the changeset), but that topics just disappear when the change moves to public phase. | == Current Implementation == |
Line 96: | Line 152: |
== Problem solved == | Assign topics to non-public changesets. A topic is like a named branch, in that it is a label stored in a changeset's extra, but that topics just disappear when the change moves to public phase (the data still exists, it's just not shown.) |
Line 98: | Line 154: |
=== What Topic solves === | Code is available at [[http://hg.durin42.com/hg-topic-experiment/]]. |
Line 100: | Line 156: |
Bookmarks are a clone of git's refs, which seems to work more poorly in Mercurial than they do in Git, in part because the synchronization parts of bookmarks aren't really done. Adding the remaining functionality to bookmarks has been challenging, and seems to be adding a lot of conceptual complexity around configuration of the synchronization mechanism that AugieFackler finds frustrating. (<- This should be dispatched in the section related to bookmark). | ==== Non-Goals ==== |
Line 102: | Line 158: |
The current implementation also makes it possible to say "what patches did I do while working on topic `issue1234`", which might be nice. | * Topics are not suitable for long term branches. We have named branches for that (and possibly also bookmarks, depending on workflow.) |
Line 104: | Line 160: |
=== What Topic may solve === | * Topics are not suitable for tracking a moving point in public history. This seems to be a perfect fit for bookmarks. |
Line 106: | Line 162: |
(Use case that exists but it is not clear if Topic should try to solve them) | |
Line 108: | Line 163: |
=== What Topic do not solve === | === Open Questions === |
Line 110: | Line 165: |
* Topic seems orthogonal to tracking content of remote repository. * Topic is not fitted for long term branch, we have named branch for that (and bookmark?) (Use case we know belong to other feature) == Open Question == * Right now we use changeset extra for storing the topic. That might lead to bonus divergence problems. |
* Right now we use changeset extra for storing the topic. That might lead to bonus divergence problems. They might be easily fixed, but should we avoid that? |
Line 122: | Line 169: |
== See also == * FeatureBranchesStruggle |
Note:
This page is primarily intended for developers of Mercurial.
Topic Plan
A (speculative) plan for topic branching that would work more seamlessly with common Mercurial workflows. Still very early prototype stage. Everything is subject to change.
Contents
1. Problem Statement
The Mercurial community has been struggling for years to define a nice way to handle 'topic' branches (sometimes also called 'feature' branches), especially when it comes to sharing them with other people (mainly for code review or other collaboration.)
Bookmarks are a clone of git's refs, which seems to work more poorly in Mercurial than they do in Git, in part because the synchronization parts of bookmarks aren't really done. Adding the remaining bits of git's refs to Mercurial has been controversial, and may represent enough of a behavior change that it's infeasible.
Named branches are visible forever in the revision history, which makes them unsuitable for feature branch work as the feature branch names rapidly pollute the output of things like hg branches.
2. Current Target
This describe the target semantic and behavior for topics.
2.1. General semantics
TL;DR; topic are an extra "light-branch" data relevant to draft changesets.
Topic is a name explicitly attached to changesets,
This Topic data is primarily meant to categorize draft changeset and fade out when things become public,
Changeset have both a topic and a 'branch'. The topic allow to gather related in progress work, while the branch data refer to the long terms line of development.
Behaviors focus on ensuring any name have a single head.
- Behaviors related to named branches behave mostly as if the draft-with topic are not on the branch (yet).
- Behaviors within a topic are similar (with minor sensible difference) to named branches one within the topic.
2.2. General effect on named branch
Changeset with topic are only aspiring to be part of the named branch, but not fully in that branch yet. when you have branch foo name foo is resolved to the heads of foo with no topic.
Three is a couple of examples:
Multiple heads are not longer ambiguous,
The name foo resolve to C,
The name bar resolve to Y,
Partial data does not have radical change on the definition,
The name foo resolve to B,
The name var resolve to Y,
Usual traversal rules apply:
The name foo resolve to B,
The name var resolve to X,
2.3. Behavior for update
This implies change in hg update behavior (but are not super relevant)
2.4. Behavior for merge
This assume hg rebase and hg merge to be identical
2.5. Behavior for push to publishing (default repo)
2.6. Behavior for push to non-publisehd repo
2.7. Stacked diffs workflow
2.8. User Transition
3. Pro and Cons
4. Other questions
5. Open ideas
This is a list of idea that emerged while brainstorming. This served as base for the current things.
- Topic could be a property attached to each changeset (grouping them by similar topic)
- Topic could fade away when changesets become public (either archived or plain dropped)
A benefit of archiving them is that users can query for topics, eg you could say hg log -r topic(issue123) which would help
- Tracking could be achieved through the naming scheme. eg:
- 'default//feature-foo' would be a topic 'feature-foo' tracking the 'default' branch.
- 'stable//issue4700' would be a topic 'issue4700' tracking branch stable.
- '@//feature-bar' would be a topic 'feature-bar' tracking bookmark '@' ?
- 'stable//issue4689//issue4700' would be a topic 'issue4700' tracking the topic 'stable//issue4689'. When topic 'issue4686' face away (because published), the tracking fallback to 'stable'.
Topics could be non contiguous (mpm idea) feature-foo -> fix-bar -> feature-foo. Allowing a streamlined work that is automatically split apart after that.
- Topics could be hierarchical 'issue4700.test' 'issue4700.preparation', activation//reference could be done at any level 'issue4700' or 'issue4700' (this could help handle branching/different approach)
pushing a new head on a new topic to a non-publishing server would be allowed.
- that is, it'd be legal to have one head per topic on a non-publishing server.
- A changeset could maybe have multiple topic.
- Augie doesn't feel great about this option just because of UI complexity.
- Users can name patches (in a sense) without mq
- One of the major complaints about evolve from veteran mq users is that their patches no longer have explicit names. Topics provide a potential way to name patches again.
6. Current Implementation
Assign topics to non-public changesets. A topic is like a named branch, in that it is a label stored in a changeset's extra, but that topics just disappear when the change moves to public phase (the data still exists, it's just not shown.)
Code is available at http://hg.durin42.com/hg-topic-experiment/.
6.0.1. Non-Goals
- Topics are not suitable for long term branches. We have named branches for that (and possibly also bookmarks, depending on workflow.)
- Topics are not suitable for tracking a moving point in public history. This seems to be a perfect fit for bookmarks.
6.1. Open Questions
- Right now we use changeset extra for storing the topic. That might lead to bonus divergence problems. They might be easily fixed, but should we avoid that?
- Should changesets be allowed multiple topics?
- How permissive should we be on topic names?