#pragma section-numbers 2 = Changesets Evolution - development page. = /!\ This page is intended for developer {i} For a user perspective see ChangesetEvolution. <> == Contributing == The simplest way to help is to grab one of: [[https://bz.mercurial-scm.org/buglist.cgi?keywords=easy,%20&keywords_type=anywords&order=Bug%20Number&resolution=---&query_format=advanced&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE&bug_status=IN_PROGRESS&component=evolution&list_id=5014|list of easy bug]] There is also a multiple well defined topic that where idea exist but needs an implementation * Rebase could make more use of obsolescence marker: * detection that part of the rebase set is already in the destination * warning about divergence creation. * [[CEDObsmarkersExchange|Obsolescence markers exchange]] (no really we have idea waiting to be implemented) * Prototype for a command bringing changeset back to life. There is more complicated part that requires attention too. * Better storage//loading//cache for markers ''(depends on marker exchange)'' * Solving the problem of [[TopicPlan|Topic Branch]] * Handling moving changesets around with the "plan" concept, * in memory merge ''(helps a lot of troubles resolution throught evolve)'' * Wide transaction capability * Continue/stop/abort for all command including evolve * In transaction content non exchangeable. * Making evolve capable of solving all troubles that user can encounter * Computing UI message about troubles from event who happened during the transaction. == Roadmap == See [[CEDRoadMap]] == Overall concept == See [[CEDConcept]] == Related Concept == Other concept not directly involved in Changeset Evolution and closely related for technical or user experience reason. * AtomicRepositoryLayoutPlan: To reduce race condition around new evolve * metadata * WideTransactionPlan: To help ability to have "pure" abort/rollback/undo, * FeatureBranchesStruggle: To help organise all your developpements branches, * TopicPlan: A possible solution to the above, * RevsetOperatorPlan: To offer proper way to travel through the * evolution-history, * PlanHistoryRewritePlan: Factorise and empower all the common history rewriting operation, * ExperimentalExtensionsPlan: To move the evolve extension into core, * CommitCustodyConcept: Top level way to follow and sign draft changeset. == In progress Features and discussion == === Using Obsolescence Marker during Rebase === There is two big issues with rebasing a set containing obsolescence changeset: * It is easy to create divergence * You get a lot of conflict when rebasing an obsolete stack on it's successors version. To enable the current implementation set the config '''experimental.rebaseskipobsolete''' to true. Current progress: * (./) rebase can skip obsolete changeset when rebased on successors, * (./) same logic as above, handling prune, * (./) same logic as above, handling split, * (./) ability to detect divergence creation and bail out, * {X} ability to rebase set with obsolescence inside the set (rebasing both precursors and successors) without creating divergence, * {X} official config to control these two behavior (either in one or two config) * {X} config on by default. === `hg evolve --list` === This is also tracked in [[https://bz.mercurial-scm.org/show_bug.cgi?id=4845|https://bz.mercurial-scm.org/show_bug.cgi?id=4845]] Evolution can compute a lot of information out of the obsolescence graph. It already use it to compute troubles and automatically solve them. Yet this information is not easily accessible to the user. We would like to gain a basic version of `hg evolve --list` that would provide all available information on current troubles. ==== Output Proposal ==== CHANGESET - TROUBLE: REASON - TROUBLE: REASON CHANGESET - TROUBLE: REASON More concrete example: 5633576f2df1: unbundle: cleanly abort on unknown ... unstable: parent 485eb2a02a2b is obsolete bumped: precursors ec2662b9629d is public divergent: precursors 4a8e21578e14 have another succcessor 84dcc37b1272 divergent: precursors 4a8e21578e14 have another succcessor 2a3010ba6f52 We want to ensure this is implemented through the 'formatter' API so we gain structured output easily "eg -Tjson" ==== Command Line API ==== We probably want * `--rev` to allow select revision to display * `--unstable`/`--bumped`/`divergent` to restrict the trouble we display. ==== Details on Each Trouble Cases ==== Here is some idea for data we could provide in each cases. This provide an handy list of case in the process. ===== Unstable from Obsolete Parent ===== * reason: unstability comes from parent being obsolete * Source: What is this obsolete parent, * Evolution target: What the evolution will turn the parent into (beware of pruned changeset) * We should mention problematic split, ===== Unstable from Unstable Parent ===== * reason: unstability comes from parent being unstable * Source: What is this unstable parent, * parent needs to be evolved before that one. ===== Unstable Merge ===== * If both parent have obsolescence/troubles, we must issue two entries ===== Bumped Changeset ===== * Point at the public changeset * Mention if we need a rebase or not * ADVANCE: Is there a commit message change ===== Divergent Changeset ===== * Point at the other divergent changeset * Point at the "greater common evolution ancestors" of divergence * Says if this GCEA is known locally * Point "greater locally known common evolution ancestors" in addition otherwise. * mention if we need a rebase or not, * The "divergent with a split" case… ===== Divergent with the other side public ===== This is actually one of the most common divergence scenario. '''We probably need a dedicated name for this'''. * We should mention that the other side is public/immutable. ===== Visible Obsolete Changeset ===== Should list them with a mention of why they are still visible? === obsmarker support in `hg strip` === We would like to be able to strip obsolescence marker related to a changeset when stripping it. We want: * (some) way to disable it ("nice way" can come later), * the obsmarker to be in the backup bundle, * A mode where we strip all markers between the stripped one and first known precursors (default?) * A mode where we strip all precursors too (and associated markers) (beware of untargeted descendant of precursors, cf drophack). The "obsmarker in the backup bundle" will requires some work because there is no other place storing obsmarkers in an on disk bundle. However, all infra should be in place as we already exchange obsmarker over the wire through a bundle. In the same go, you can consider adding obsmarker support to `hg bundle` through the "variants" part of the type. === `hg evolve --continue/--abort/--drop` === Currently evolve implement a super basic state format that does not allow a proper "multi step" behavior. ==== About `--continue` ==== Current issues * does not remember the currently evolved set (just finish the current one) * does not work for `--bumped` or `--divergent` We need to update the format on disk to allow these. ==== About `--abort` ==== This does not exists but it would be useful. * We need to know the evolved set, * We must also record and remove obsmarker we created in the process. ==== About `--drop` ==== Currently, user can "abandon" his evolve at any time. leaving half of the thing evolved and the other one still unstable. That is a pretty cool feature we want a way to keep. Adding a flag could be a way. openning the way to similar feature in other multi step command. Name is not frozen, this is the first time we mention it. Maybe we just want `hg up -C` to be that, but it seems a bit too easy to run by mistake. === Tagging draft changeset === Currently tagging draft a changeset may lead to issues when the tagged changeset is rewritten and its hash change, making the tag invalid. Here is a small (draftish) list of ideas to handle the question, the first one "rewriting the tag file when we evolve/rewrite the tagging changeset" is probably the way to go. Mailing list discussion about this: https://www.mercurial-scm.org/pipermail/evolve-testers/2016-May/000178.html ==== rewriting the tag file when we evolve/rewrite the tagging changeset ==== When the tagging changeset is evolved (changed from a descendant of the old tagged, to the new version), we could rewrite the content of the tag file. Pro: * Does "the right thing"™ * Works even if the tagged changeset is pulled -after- the rewrite. Cons: * Only work when the tagging changeset is a descendant of the tagged, * Does not handle the local case. ==== Warn when pushing a draft tag ==== The idea is that pushing a tagged changeset as draft increase the risk of rewrite, so warning could help having user think about turning them public. Pro: * easy to do, * can be reverted when we need something better, * prevent the error to pass silently, Cons: * Does not actually solve the problem, * Does not handle the local case. ==== Warn when rewriting a draft tag ==== Pro: * easy to do, * can be reverted when we need something better, * prevent the error to pass silently, Cons: * Does not actually solve the problem, ==== Turning the changeset public on tagging ==== Pro: * Prevent any tag rewrite issue, * easy to do, * handle both local and remote case, Cons: * loose the ability to fix tagging error before publishing, * break backward compatibility, * hard to revert if we get something better, ==== Turn the tagged changesets public on push ==== Pro: * Turn changeset public at the time it become more complicated, Cons: * loose the ability to fix tagging error before publishing, * break backward compatibility for non-publishing repo, * hard to revert if we get something better, * do not handle the local case. ==== refuse to tag draft ==== Pro: * Get rid of the issue (almost) entirely, * handle local and remote case, Cons: * massive backward compatibility breakage, sensible user script will break, * hard to revert if we get something better === Obsolescence Marker Discovery === * See dedicated page: ObsolescenceMarkersExchange === amend/uncommit/recommit/etc === A recurring discussion is "What should be 'base' for the 'amend' operation" (or other related command). The complexity of the situation comes from the fact we have 3 states of interest 1. `wc()`: The working copy content (on disk file) 2. `p1()`: The working copy parent content (commit content, affected by commands) 3. `p1()~1`: The working copy parent (commit content). Various core command already allow to interact with these layers. * The `commit` command move content from `wc()` to `p1()` (creating a new `p1()`) in the process), * The `commit --amend` is just a variation of that moving content from `wc()` to `p1()` (reusing the existing one). * The `revert` command move content from `p1()` to `wc()` * The `revert --rev` command move content from any commit content to `wc()` Evolve have various commands in this area too. * The `amend` command mimic `commit --amend`, moving content from `wc()` to `p1()` * The `uncommit` command move content from `p1()~1` to `p1()`. A common question is to change the default of `amend` to use `p1()~1` as base. Picking change from `wc()` when selected and resetting to `p1()~1` for excluded content. "Just changing the default" is not a solution here. We have multiple possibilities (because we have 3 states to select from) and if we change from one to the other, some people will just start asking for the other one instead.CategoryNewFeatures However, having an easy way to select the mode would be nice, gather all usecase into a single command would be preferable. Building a good UI for that might allow us to remove the dedicated `uncommit` command and provide a `recommit` capabilities that people have been asking for. === Record types of operation === Storing more information about what the type of rewrite in obsolescence markers would be useful. The idea is to leverage the bitfield in the markers to record various kind of actions. ==== Recorded actions ==== * did the "diff" changed, (eg: amend) * did the parent changed, (eg: rebase, but not plain evolve) * did the commit message got edited, * did the changeset metadata got rewritten. And probably these extra data too: * is the changeset purely identical to another (rewind), * is the rewrite part of a fold. The various edition command will be responsible for adding useful information: * a `hg amend` that update the diff will create a markers recording the "content changes", * a `hg amend -e` that only update he commit message will record the "message change", * a `hg rebase` will record the "parent change", * a `hg amend` that update the message, the content and user will record these three things (content, message and meta changes). * `hg histedit` would record the right operation according the the action. ==== Advantages ==== * '''Compact''': Since we use the (existing) bitfield, the storage cost is free (or minimal if we need to adds an extra Byte of bitfield). Accessing the data is also very cheap: * '''Compoundable''': We'll often needs to combine multiple markers to reports changesets between two revisions (eg: we do not have the intermediate revision locally). the bit approach makes it trivial to compound the information. We can display display the same final information when the same result if obtained from different path (eg: from two markers `[content change; message change]` or from one markers `[content change | message change]`). * '''UI Abstraction''': since we record the "effect" information, we abstract the command names. This makes use more agile about the actual UI. User can use their own "hg myownrewritetool" command and still record information useful for the other users. ==== Usage ==== Having that data will help providing information about the obsolescence history. Example: {{{ @ ac28e3 durham / First commit | | o d4afe7 durham | | Second commit | | | x 8e9a5d (Amended as ac28e3) durham |/ First commit | }}} == See Also == * entry points: [[http://bz.mercurial-scm.org/buglist.cgi?keywords=easy,%20&keywords_type=anywords&order=Bug%20Number&resolution=---&query_format=advanced&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE&bug_status=IN_PROGRESS&component=evolution&list_id=5014|list of easy bug]] * contributing: [[https://bz.mercurial-scm.org/buglist.cgi?bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE&bug_status=IN_PROGRESS&component=evolution&keywords_type=anywords&list_id=9370&order=Bug%20Number&query_format=advanced&resolution=---|list of all issues]] * User: ChangesetEvolution * Planning: [[CEDRoadMap|Road Map]] * Core Concept: [[CEDConcept|Concept and important sub-issue]] * Interface: [[ChangesetEvolutionDevelUI|Generic user interface discussion]] * Vabulary: [[CEDVocabulary|How should we name things]] * Exchange: [[CEDObsmarkersExchange|Information about obsolescence markers exchange and discovery]] * Rebase: [[CEDRebase|Behavior with "hg rebase"]] * Cycles: [[CEDCycles|Handling of cycle in the obsolescence markers]] * Format: [[CEDObsstoreFormat|Archived page about the "obsstore" format]] ---- CategoryNewFeatures CategoryDeveloper CategoryEvolution