view docs/index.rst @ 3846:f9dad99a90d5

evolve: create a new commit instead of amending one of the divergents This patch changes the behavior of evolve command while resolving content-divergence to create a new commit instead of amending one of the divergent ones. In past, I have made this change, backed out this change and now today again I am doing this change, so let's dive in some history. Using cmdrewrite.amend() was never a good option as that requires hack to delete the evolvestate and also gives us less control over things. We can't make the commit on top of different parents as that of content-divergent ones. Due to all these, I first made this change to create a new commit instead of amending one. But, after few days, there was flakiness observed in the tests and turned out that we need to do some dirstate dance as repo.dirstate.setparents() does not always fix the dirstate. That flakiness was a blocker for progress at that time and we decided to switch to amend back so that we can have things working with some hacks and we can later fix the implementation part. Now, yesterday while tackling resolving content-divergence of a stack which is as follows: C1 C2 | | B1 B2 | | A1 A2 \/ base where, A1-A2, B1-B2, C1-C2 are content-divergent with each other. Now we can resolve A1-A2 very well because they have the same parent and let's say that resolution leads to A3. Now, we want to resolve B1-B2 and make the new resolution commit on top of A3 so that we can end up something like: C3 | B3 | A3 | base however, amending one of the divergent changesets, it's not possible to create a commit on a different parent like A3 here without some relocation. We should prevent relocation as that may leads to some conflicts and should change the parent before committing. So, looking ahead, we can't move with using amend as still using that we will need some relocation hacks making code ugly and prone to bad behaviors, bugs. Let's change back to creating a new commit so that we can move forward in a good way. About repo.dirstate.setparents() not setting the dirstate, I have researched yesterday night about how we can do that and found out that we can use cmdrewrite._uncommitdirstate() here. Expect upcoming patches to improve the documentation of that function. There are lot of test changes because of change in hash but there is no behavior change. The only behavior change is in test-evolve-abort-contentdiv.t which is nice because creating a new commit helps us in stripping that while aborting. We have a lot of testing of content-divergence and no behavior change gives enough confidence for making this change. I reviewed the patch carefully to make sure there is no behavior change and I suggest reviewer to do the same.
author Pulkit Goyal <7895pulkit@gmail.com>
date Wed, 13 Jun 2018 17:15:10 +0530
parents 2a337fcedd5e
children 9fe35f4bc173
line wrap: on
line source

.. Copyright © 2014 Greg Ward <greg@gerg.ca>

==================================
Changeset Evolution with Mercurial
==================================

`evolve`_ is a Mercurial extension for faster and safer mutable history. It
implements the `changeset evolution`_ concept for `Mercurial`_.

* It offers a safe and simple way to refine changesets locally and propagate
  those changes to other repositories.

* It can automatically detect and handle the complex issues that can arise from
  exchanging draft changesets.

* It even makes it possible for multiple developers to safely rewrite the same
  parts of history in a distributed way.

* It fully respects the Phases concept so users will only be able to rewrite
  parts of the history that are safe to change. Phases have been part of
  Mercurial since early 2012.

.. _`evolve`: https://www.mercurial-scm.org/wiki/EvolveExtension
.. _`Mercurial`: https://www.mercurial-scm.org/

Installation and setup
----------------------

We recommend you subscribe to the `evolve-testers`_ mailing list to stay up
to date with the latest news and announcement.

.. _`evolve-testers`: https://www.mercurial-scm.org/mailman/listinfo/evolve-testers

Using pip::

    pip install --user hg-evolve

Then add in your `hgrc` config::

   [extensions]
   evolve=

You can easily edit the `hgrc` of a repository using `hg config --local`.
Alternatively, you can edit your user configuration with `hg config --edit`.

Table of Contents
-----------------

.. toctree::
   :maxdepth: 2

   index
   user-guide
   sharing
   concepts
   from-mq
   commands
   known-doc-issues

.. _`changeset evolution`:

What is Changeset Evolution?
----------------------------

With core Mercurial, changesets are permanent and immutable. You can
commit new changesets to modify your source code, but you cannot
modify or remove old changesets.

For years, Mercurial has included various commands that allow
history modification: ``rebase``, ``histedit``, ``commit --amend`` and so forth.
However, there's a catch: until now, Mercurial's various mechanisms for
modifying history have been *unsafe*, in that changesets were
destroyed (“stripped”) rather than simply hidden and still easy to recover.

``evolve`` makes things better by changing the behaviour of most existing
history modification commands so they use a safer mechanism (*changeset
obsolescence*, covered below) rather than the older, less safe *strip*
operation.

``evolve`` is built on infrastructure in core Mercurial:

  * *Phases* (starting in Mercurial 2.1) allow you to distinguish
    mutable and immutable changesets.

  * *Changeset obsolescence* (starting in Mercurial 2.3) is how
    Mercurial knows how history has been modified, specifically when
    one changeset replaces another. In the obsolescence model, a
    changeset is neither removed nor modified, but is instead marked
    *obsolete* and typically replaced by a *successor*. Obsolete
    changesets usually become *hidden* as well. Obsolescence is a
    disabled feature in Mercurial until you start using ``evolve``.

Some of the things you can do with ``evolve`` are:

  * Fix a mistake immediately: “Oops! I just committed a changeset
    with a syntax error—I'll fix that and amend the changeset so no
    one sees my mistake.” (While this is possible using default
    features of core Mercurial, changeset evolution makes it safer.)

  * Fix a mistake a little bit later: “Oops! I broke the tests three
    commits back, but only noticed it now—I'll just update back to the
    bad changeset, fix my mistake, amend the changeset, and evolve
    history to update the affected changesets.”

  * Remove unwanted changes: “I hacked in some debug output two
    commits back; everything is working now, so I'll just prune that
    unwanted changeset and evolve history before pushing.”

  * Share mutable history with yourself: say you do most of your
    programming work locally, but need to test on a big remote server
    somewhere before you know everything is good. You can use
    ``evolve`` to share mutable history between two computers, pushing
    finely polished changesets to a public repository only after
    testing on the test server.

  * Share mutable history for code review: you don't want to publish
    unreviewed changesets, but you can't block every commit waiting
    for code review. The solution is to share mutable history with
    your reviewer, amending each changeset until it passes review.

  * Explore and audit the rewrite history of a changeset. Since Mercurial is
    tracking the edits you make to a changeset, you can look at the history of
    these edits. This is similar to Mercurial tracking the history of file
    edits, but at the changeset level.

Why the `evolve` extension?
---------------------------

Mercurial core already has some support for `changeset evolution`_ so why have a
dedicated extension?

The long-term plan for ``evolve`` is to add it to core Mercurial. However,
having the extension helps us experiment with various user experience
approaches and technical prototypes. Having a dedicated extension helps current
users deploy the latest changes quickly and provides developers with low latency
feedback.

Whenever we are happy with a experimental direction in the extension, the
relevant code can go upstream into Core Mercurial.

Development status
------------------

While well underway, the full implementation of the `changeset evolution`_
concept is still a work in progress. Core Mercurial already supports many of the
associated features, but for now they are still disabled by default. The current
implementation has been usable for multiple years already, and some parts of it
are used in production by multiple projects and companies (including the
Mercurial project itself, Facebook, Google, etc…).

However, there are still some areas were the current implementation has gaps.
This means some use cases or performance issues are not handled as well as they
currently are without evolution. Mercurial has been around for a long time and
is strongly committed to backward compatibility. Therefore turning evolution on
by default today could regress the experience of some of our current users. The
features will only be enabled by default at the point where users who do not use
or care about the new features added by evolution won't be negatively impacted
by the new default.

You can find the `evolution roadmap in the wiki`_.

.. # .. _`this query`: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE

Resources
---------

  * For a practical guide to using ``evolve`` in a single repository,
    see the `user guide`_.
  * For more advanced tricks, see `sharing mutable history`_.
  * To learn about the concepts underlying ``evolve``, see `concepts`_
    (incomplete).
  * If you're coming from MQ, see the `MQ migration guide`_ (incomplete).

.. _`user guide`: user-guide.html
.. _`sharing mutable history`: sharing.html
.. _`concepts`: concepts.html
.. _`MQ migration guide`: from-mq.html
.. _`evolution roadmap in the wiki`: https://www.mercurial-scm.org/wiki/CEDRoadMap