sapling/remotenames
2018-01-03 06:15:47 -08:00
..
.hgignore remotenames: move into remotenames/ dir 2018-01-03 06:15:47 -08:00
Makefile remotenames: move into remotenames/ dir 2018-01-03 06:15:47 -08:00
README remotenames: move into remotenames/ dir 2018-01-03 06:15:47 -08:00
setup.py remotenames: move into remotenames/ dir 2018-01-03 06:15:47 -08:00

.. -*-restructuredtext-*-

===========
remotenames
===========

------------
Introduction
------------

Keep track of remote names (branches and bookmarks) in Mercurial.

With this extension installed, Mercurial's behavior regarding bookmarks is
changed. The core of this extension is to keep track of remote bookmarks and
branches and to make a better user experience. It exposes up to three new
namespaces based on the branch heads and bookmarks available in other
repositories. The three namespaces are:

  * remotebranches: the heads of each branch on the peer repo (default: on)

  * remotebookmarks: the bookmarks from the peer repo (default: on)

  * hoistedbookmarks: a "short name" interface for hoisting a single peer's
    remote bookmarks into the top-level namespace, allowing workflows to stay
    the same when referring to bookmarks on the chosen peer (default: 'default')

For example, when you pull from a repository listed in .hg/hgrc's ``[paths]``
section, you get output similar to the following::

 o  f3d8 @
 |  more trunk
 |
 o  824e
 |  trunk
 |
 | o  2b7b feature
 | |  feature: more new stuff
 | |
 | o  a342
 |/   feature: new stuff
 |
 o    52a8 (smf/default) [smf/@]
 |\   merge stable into default
 | |
 | o  9c95
 | |  chug along trunk
 | |
 o |  ea15 stable (smf/stable)
 | |  fix for stable

What this output is showing is that the head of the default branch in a repo at
path ``smf`` is ``52a8``. This is labeled above as ``(smf/default)``. Similarly,
the bookmark ``@`` was last seen on ``smf`` at the ``52a8`` changeset. Both
remote names cannot move unless you push or pull from the remote server.

Remote names are discovered by sending a single extra request to the Mercurial
server after a push or pull is complete. This extension works properly with
paths from the schemes extension included with Mercurial. Other extensions which
perform varying kinds of manipulation on the repository path may not function
as expected.

This extension is built on top of the Mercurial namespace API introduced in 3.3.

------------
Installation
------------

To enable the extension, you must add an entry to the ``[extensions]`` section
of your ``hgrc`` file::

  [extensions]
  remotenames = /path/to/hgremotenames/remotenames.py

----------------
Behavior Changes
----------------

Expect changes. Most features are enabled by default to give you an idea of
the possibilities available with this workflow.

Since this extensions keeps track of remote bookmarks, we no longer clone or
pull remote bookmarks by default. Therefore, pulling from a remote server will
no longer update your local bookmarks. This has the rather large beneficial
side-effect of completely eliminating bookmark divergence, a complicated and
difficult concept to understand, explain, and work with.

The commands ``bookmarks``, ``branches``, and ``log`` all gain a ``--remote``
flag to display remote names. This will also unhide obsolete changesets if
you are working with the Changeset Evolution extension.

Another big behavior change is that of a bare ``hg push``. For changesets that
do not create a new remote head AND are only reachable by a local bookmark,
``hg push`` will abort and not push these changesets. Hopefully, this is
behavior is clear with the following example::

  hg clone foo
  cd foo
  hg book feature
  # <hack, hack, hack>
  hg push
  pushing to foo
  searching for changes
  abort: push creates new anonymous head without the bookmark: 'feature'
  (use 'hg push -B feature' to create a new remote bookmark)

This behavior change is intended to prevent accidentally pushing an unnamed
('anonymous') head to a remote repository. To enforce this style of workflow,
read about the ``forceto`` configuration option below.

-------------------
Cloning and Pulling
-------------------

As mentioned above under the ``Behavior Changes`` section, pulls by default
will not sync normal bookmarks between the two repositories. This is also the
case with cloning. In effect, bookmarks in the ``remotenames`` world are no
longer a shared namespace among peers; rather, they are distinct namespaces that
need to be manually and explicitly synchronized among peers during pull
operations. During push operations, the manual synchronization can be achieved
with the ``--to`` option described in the previous section.

To re-enable the bookmark synchronizing behavior on ``clone`` and ``pull``,
set the ``syncbookmarks`` configuration option::

  [remotenames]
  syncbookmarks = True

-------
Pushing
-------

When pushing changes to another repository, ``remotenames`` introduces a new
flag, ``--to`` (``-t``) which drastically changes the behavior of ``push``
to be more friendly in a ``remotenames`` world. The ``--to`` flag requires
the name of the remote bookmark to push (without any ``remote/`` prefix).
For more on ``hg push`` behaviour, see the Tracking section.
When ``--to`` is specified, the default push rev (``-r``) will be ``.``.
Another rev may be specified, but only one rev may be specified or the push
will abort. The specified rev, and it's ancestors, will be pushed to the
remote repository, and the remote repository will have the named bookmark
updated to point to this revision, subject to the following constraints
(unless ``--force``/``-f`` is specified):

 * The remote bookmark must already exist (it will be created with ``-f``)
 * The remote bookmark rev must exist in the local repo (subset of the below)
 * The pushed rev must be a descendant of the current remote bookmark
 * A special case of the above: the remote bookmark already points at rev

Using ``--to`` also disables other flags to avoid confusion. ``hg push --to``
will abort if any of the following flags are specified:

 * ``--bookmark`` / ``-B``
 * ``--branch`` / ``-b``
 * ``--delete`` / ``-d``

There is a new config option to enforce using ``--to`` if that is appropriate
in your chosen workflow. To enable it, set the option ``forceto``::

  [remotenames]
  forceto = True

In this mode, to push revs to a peer, you must specify a name with the ``--to``
flag. You can still delete a remote bookmark in this mode with the added
``--delete`` flag to push as well.

Finally, there is another new flag for push, ``--delete``, which allows remote
bookmark to be deleted without deleting any local bookmark or pushing any revs.

---------
Templates
---------

Remotenames adds up to four new template keywords: ``remotebranches``,
``remotebookmarks``, ``remotenames`` (a combination of the first two), and
``hoistedbookmarks``, which are up to one peer's remote bookmarks, lifted into
the main namespace (eg, not requiring a pathname prefix).

For example, the diagram in the introduction above uses the template
``({remotebranches}) [{remotebookmarks}]``. Alternatively, you could use
``remotenames`` to include both namespaces. If you set the configurable option
``suppressbranches``::

  [remotenames]
  suppressbranches = True

Then ``remotenames`` will only display the branch name if there is no bookmark
present on the same node.

---------------------------
Aliasing and Renaming Paths
---------------------------

For the example in the Introduction, the name ``smf`` is used instead of
``default`` because the .hg/hgrc is as follows::

  [paths]
  default = http://smf.io/hgremotenames
  smf = http://smf.io/hgremotenames

Since those two paths are equal, the non-default name is chosen. This effect
can also be achieved by using the 'rename' configuration option:

  [remotenames]
  rename.default = smf

Mercurial has several overloaded terms, including ther word ``default`` which
can refer to the implicit named branch or the clone source path. Since
remotenames uses the peer's path name, it is common to see remotenames prefixed
with ``default/``. This can be confusing since branches also often have that
name. Therefore, remotenames allows you to rename a path to something else.
One common choice is to rename ``default`` to ``remote``. Thsi would result in
remote names from this repository showing up as ``remote/bookmark`` instead of
``default/bookmark``. Push and pull to this name will also work.

Finally, there is an ``alias.default`` setting:

  [remotenames]
  alias.default = True

Setting this will drop the remotebranch name ``smf/default`` into just ``smf``.
It is another way to reduce the nubmer of times that ``default`` shows up in
the UI.

------------------
Transition Helpers
------------------

Using remotenames can be a big departure from previous workflows, so in addition
to renaming and aliasing, the remotenames extension offers a few other options
to make migrating to a remotenames easier. First is the ``transitionbookmarks``
configuration option:

  [remotenames]
  transitionbookmarks = @
      foo

With this setting, remotenames will delete the local bookmarks ``@`` and ``foo``
the first time the extension is run (and pulls the remotenames from a peer).
In order to prevent these bookmarks from being re-created and causing confusion,
you can set the ``disllowedbookmarks`` config:

  [remotenames]
  disallowedbookmarks = @
      foo

At which point mercurial's ``bookmarks`` command will refuse to create new
bookmarks with these names.

-------
Revsets
-------

Remotenames makes the following new revsets available: ``pushed()``,
``upstream()``, ``remotebranches()``, ``remotebookmarks()`` and
``remotenames()``. The ``pushed()`` revset returns all revisions that are have
been pushed to any repository tracked by remotenames. The ``upstream()`` set is
those revisions which are in a repository whose path is listed in the
``upstream`` field of the ``[remotenames]`` configuration section. If there is
no ``remotenames.upstream`` setting, it defaults to behaving identically to
``pushed()``. The ``remotenames()`` revset simply returns all remote branches
head changesets.

--------
Tracking
--------

Remotenames introduces a new concept to bookmarks called ``tracking``. Its use
it entirely optional. In order to start using it, pass the --track (-t) flag
to the bookmarks command:

  hg bookmarks mybook --track remote/@

Tracking sets up several default behaviors:

* When pushing, if the current bookmark tracks a remote bookmark, the push
  destination will default to the tracked path and bookmark. For example,
  if the ``mybook`` local bookmark is current and is tracking ``remote/@``,
  then calling ``hg push`` with be equivalent to calling
  ``hg push remote -r mybook --to @``. This gives a default peer and default
  name to push to. We hope this will optimize many workflows.

* When rebasing (if the rebase extension is enabled), ``hg rebase`` with no
  arguments changes behavior as well. When the current bookmark is tracking
  another name, ``hg rebase`` will default to rebasing on top of the tracked
  name. For example, if ``mybook`` is the current bookmark, ``hg rebase`` with
  no arguments will be the equivalent of: ``hg rebase -b mybook -d remote/@``.
  Note that in this usage, the tracked name does not have to be a remote
  bookmark: bookmarks can track other local bookmarks, and rebase will use
  that as a default rebase destination.

* When pulling with the ``--rebase`` flag from an active bookmark that's
  tracking a remote bookmark, local changes are rebased on that remote bookmark.

* Finally, tracking allows a distance calculation, so you know how far ahead
  and behind a given bookmark is from the name it is tracking. In the diagram
  in the Introduction above, for example, the ``feature`` bookmark is 2 behind
  and 2 ahead of the @ bookmark. Distance is covered in more detail in the
  next section.

To see a listing of what a bookmark is tracking, use ``hg bookmarks -v``.

--------
Distance
--------

For actions that create commits or update to another changeset (``commit``,
``rebase``, ``histedit``, ``update``, etc.), the distance to the default path
is written in .hg/remotedistance. The format of this file is ``'SIGN NUMBER'``,
e.g. ``'+ 10'`` or ``'- 7'``. This is handy for use in your shell prompt.

For example, the following is in my bash prompt::

  remote="$(less $repo_dir/.hg/remotedistance 2>/dev/null)"
  sign="⇡"
  [[ ${remote:0:1} == "-" ]] && sign="⇣"
  distance="$(echo $remote | cut -d ' ' -f2)"
  remote=""
  [[ "$distance" != "" && "$distance" != "0" ]] && remote=" $distance$sign"

This tells me how many commits I'm ahead or behind in my prompt.

By default, the distance is caclulated after each write operation and cached for
quick lookup. However, in repositories with high commit rates, the distance
calculation can take a long time, so you can disable it using the following
configuration bits:

  [remotenames]
  cachedistance = False

It is also possible to disable all distance calculation (even those in tracked
bookmarks) with the ``calculatedistance`` knob:

  [remotenames]
  calculatedistance = False

--------
Feedback
--------

The authors appreciate feedback and would be glad to hear from you. Please ask
questions or provide feedback on the Mercurial mailing lists. We actively
follow these lists and are excited to have people try this extension and let
us know what they think.

Thank you for trying out remotenames!