Fixing default behavior of bookmarks.

Valentin Gatien-Baron vgatien-baron at janestreet.com
Mon Jan 27 23:03:03 UTC 2020


Hi,

I've finally found some time to reply to this.

I couldn't find a place that explains concisely the behavior of
bookmarks, which I thought would be useful to think through this.  I
included some notes [1], if that's useful to someone else.

A tiny bit of context on our use of bookmarks. People put bookmarks on
the tip of their work in progress, and push them to a central server.
So that server sees a lot of bookmarks come, move, and go. People
manipulate not just the bookmarks they create, but also regularly
bookmarks holding work they have to review.


I don't think I have seen the problem you linked to about `hg update`,
but the description is terse, so I don't think I understand what is
the series of steps that leads to the bad behavior.

The problems we do get are as follows, from roughly most problematic to
least problematic (if we didn't work around them).

No way to request that a push must push a bookmark (or fail). `push
-r` pushes the revision pointed to by the bookmark (and may or may not
send the bookmark too), `push -B` overwrites whatever is on the other
side. This is https://phab.mercurial-scm.org/D6776 .
We work around that one by making `push -r bookmark` fail if the
bookmark can't be pushed, but I'd certainly prefer to have something
nice in hg itself.

`pull` creates an accumulation of bookmark locally: if a remote
contains bookmarks {a} at time t0, {b} at time t1, {c} at time t2
(which is expected for short lived bookmarks), any repo that pulled at
t0, t1 and t2 will have bookmarks {a, b, c} locally.
For people, this also means that if a bookmark moved sideways in the
remote, any pull from now on gets a message "created divergent
bookmark foo at default", whether they know anything about foo or not.
For tools (CI, code review, backups), this is merely awkward: you can
workaround this by replacing "hg pull" by something like "set -o
pipefail; rm -f .hg/bookmarks; hg pull | { grep -v "added bookmark" ||
true; }".
We work around this by having pull delete extra bookmarks
(specifically, any local bookmark that points to a non outgoing
revision). This probably only works in a centralized setup.

This notion of current-bookmark (as opposed to active-bookmark) is
awkward. `hg pull` interferes with `hg commit` for instance, because
`hg pull` may change the active bookmark into being merely current,
which `commit` does not consider. We have to account for this when we
pull in people's repositories, and in particular this behavior makes
me think that [share -B] (or the bookmarks-in-store requirement)
should be error prone (pull in one share, mess up commit in other
share).
No workaround there. I've contemplated making hg consider that the
active bookmark is at `wdir()` instead of `p1()`, such that pull
cannot move the active bookmark forward. That may be an improvement,
but wouldn't help with `share -B`. I think `git` handles this by
making it so that, in hg terminology, the clone knows about the active
bookmark of all shares.

`push` moves all bookmarks that can be moved forward. I don't know if
this is for consistency with `push` pushing all the heads by default,
but it sounds like a recipe for pushing unintended things.
We only push the active bookmark or bookmarks passed at the command
line (and we don't push all heads either).

Pushing a bookmark but no commits results in hg printing "no changes
found" and exiting code 1 (which is not specific to bookmarks, pushing
merely phases or obsolescence markers behaves the same). This confuses
people regularly (we may have some changes to this behavior, but I
think it's confusing even as described here). The exit 1 is annoying
for automation (can't trust that exit 1 means no commit, as rejections
from server hooks can also result in exit 1 IIRC).

In `pull` or `clone`, the "added this bookmark" or "updating that
bookmark" prints are extremely spammy (with many bookmarks, and
frequent changes), whether interactively or in logs of tools.
We remove all these prints (and in fact others like "searching for
changes" or "adding changesets").


Valentin




[1]
My notes about what hg does.

- hg pull
  - add all remote-only bookmarks locally
  - for bookmarks on both sides
    - if remote rev is not pulled, do nothing
    - if remote rev is pulled and is ahead of local, advance bookmark
    - otherwise create conflicting bookmark
  - for local-only bookmarks, do nothing
  - the active bookmark may be advanced, becoming current-but-not-active
  - print the state of each bookmark
- hg commit
  - advances active bookmark
  - sometimes delete conflicting bookmark, on merge conflict
- hg merge
  - without -r, try to merge with the @default bookmark if any
- hg clone
  - copies all the bookmarks
  - print the state of each bookmark
- hg share
  - does not copy the bookmarks
  - but with -B, all shares share the bookmarks (or similarly, the
    option to make bookmarks be part of the store)
- hg push
  - for all bookmarks that exist on both sides, if local rev is
    ahead of remote and is being pushed, advance remote bookmark
  - -B will export bookmark and overwrite anything on the remote
- hg update
  - hg up -r bookmark makes the bookmark active
  - anything else doesn't make the bookmark active
- hg id
  - shows slash separated bookmarks
- hg book
  - can act on all bookmarks
  - not clear what's up with active vs current bookmarks

On Thu, Nov 14, 2019 at 11:08 AM Pulkit Goyal <7895pulkit at gmail.com> wrote:

> Hi everyone,
>
> From some months we (mostly Augie and me) are discussing that we
> should fix the default behavior of bookmarks. The current behavior is
> buggy in different ways and I know atleast three companies (Facebook,
> Janestreet and one more) which uses bookmark but has modified the
> default behavior.
>
> This is not about whether bookmarks are a good way to name things. I
> think refs are one of the good ways to name commit and current
> bookmark behavior is not best experience in that space.
>
> There has been various discussions on this and efforts too. I am able
> to find two plan pages:
>
> * https://www.mercurial-scm.org/wiki/BookmarkUpdatePlan (this does not
> seem to be done)
> * https://www.mercurial-scm.org/wiki/BookmarksPlan
>
> Sandu recently proposed a change in
>
> https://www.mercurial-scm.org/pipermail/mercurial-devel/2019-October/135395.html
>
> There has been efforts from Fb in past to improve things by moving
> remotenames to core and trying to change related things. Sandu has
> contributed a bookflow extension which tries to solve some of the
> issues and has some patches in review too.
>
> My bookmarks usage is pretty limited, but I do extensively use
> git-like refs at work. It will be nice to start discussing the
> problems which users face right now and solutions for that. So, if you
> have suggestions or issues around current bookmark behavior, it's a
> nice time to speak up.
>
> I hope in the end we can make some BC changes and make the default
> behavior saner for everyone.
>
> Thanks!
> Pulkit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20200127/896577ec/attachment.html>


More information about the Mercurial-devel mailing list