Bookmarks: don't push local bookmark heads by default?

Pierre-Yves David pierre-yves.david at logilab.fr
Fri Jun 8 10:05:38 CDT 2012


On Sat, Jun 02, 2012 at 04:16:21PM -0500, Matt Mackall wrote:
> One possibility is that when an outgoing head has a bookmark that's
> local-only, we treat the commits as local-only as well and refrain from
> pushing it. This lets Alice make a private bookmark branch without
> needing to worry about it getting pushed by accident.


TL;DR: don't do that! Instead we should abort//warn when pushing a head without
       it's bookmark. (And migrate to local/global bookmark, see table at the end)

*Yes* the fact that you push bookmarked changeset without the bookmark is
confusing, annoying and one of the major issue with bookmark.


*No* I do not like this proposal:
=====================================================================


- You already sumup the downside and I feel they are pretty strong.

  I "regularly" use bookmark to add "local label" to commit. This label -may-
  something ends on head and I will be confused and annoyed it if magically
  -stop- pushing change because I **finally moved** the 'test-on-sulfur' on a head.

  Another example of strange behavior:

      The very same command will push different head when used on two
      differents repo. Just the two remote does not have the same bookmark (and
      you have not easy way to know which bookmark are available on remote)


- I'm not convinced by the way this try to fix: "it's not making it very easy
  for Alice to make a "local branch".

  The answer here is: "enforce the branch is not pushed".

  And we -already- have a concept for "ensure this changeset are not pushed" (secret phase).

  The real point we should seek is "ensure the branch is not pushed without
  it's bookmark.". See my counter-proposal below.

- This goes down the "Let's do the exact same thing than git branch". This is
  very bad. This ultimately lead the need to have the exact same behavior than
  git branches, requesting everything to be bookmarked to have a descent user
  experience.

  One of the strength of mercurial is to *not* have mandatory label on
  everything! Let's preserve it.

  I believe we can find our own way for bookmark.



This is why I do have another simple proposal:
=====================================================================


Abort when pushing bookmarked heads without they bookmark:

  $ hg push
  abort: pushing heads b4b49c313571 without it bookmark "elephants" unknown remotely
  (do you want to use -B to push bookmark of to turn you branch secret ?)


The user will have three options to be able to push:

A) pushing it's bookmark remotely

 $ hg push -B elephants

B) making its local only changeset secret: (non-contractual revset)

 $ hg phase --force --secret "draft() and ::elephant"

C) Add yet another option to push: (non-contractual option name)

 $ hg push --yes-push-please-this-bookmark-is-local-only

A lower version of this is to just warn when this happen

  $ hg push
  warning: pushed heads b4b49c313571 without it bookmark "elephants" unknown remotely
  (use "hg push -B elephant" to push it)


Going even further:
=====================================================================

(This part is not directly linked to the discussion but related to "how we can
make bookmark usable")

I fell like the "ideal" alternative will be to always push all bookmark by
default the same way we always pull and clone them. However:

> Another alternative, pushing "local" bookmarks always, is probably off
> the table as it means anyone who is depending on having a private
> namespace today gets a nasty surprise on upgrade.

But it is clear that they are two usages for bookmarks:

    - pointer for lightweight branches that we want to share

    - local marker for local only purpose
      (yes, we had local tag for that)

And I think we should make this distinction explicit:

Bases rules:

    1) Bookmark are either *local* or *global*.

    2) *Global bookmark* are (almost) always pushed, pull and cloned.

    3) *Local bookmark* are never pushed, pulled or cloned. (they don't appear
       in pushkey)

    4) bookmark are created global unless "--local" flag is given

    5) you can switch bookmark from *global* to *local* manually

Backward compat rules:

    1) Bookmark created with older version of mercurial are *old*

    2) *Old bookmark* seen on remote repo are promoted to *global*

      $ hg push
      bookmark "elephants" promoted to global

    3) *Old bookmark* on a *pushed head* warn if bookmark is not known remotely

      $ hg push
      pushed head b4b49c313571 without it's old bookmark "elephants"
      (do you want it global ? see "hg help bookmark")

    4) *Old bookmark* behave as local bookmark otherwise

    5) *Old bookmark* can be switched to *global* or *local* manually


Interaction with secret changeset:

    1) If they are unknown remotely, global bookmark on secret changeset are not
       pushed.

    2) If they are known remotely, global bookmark on secret changeset are

       pushed as if they where on the tip most draft ancestors of their current
       location. (if they are multiple heads to (public() and ::bookmarked) we
       create divergent bookmark and/or warn)

       This point should be done even for the current implementation.



Summary table:

    legend:

        horizontal:

            :secret: are the bookmark on a secret changeset
            :head:   are the bookmark on a head
            :remote: are the bookmark know by remote ?
            :local:  are the bookmark known locally

        vertical :

            :current: how bookmark currently behave in the current code.
            :old:    bookmark created with older mercurial version
            :local:  new local only  bookmark
            :global: new global bookmark (new default)

        cell:

            :ignore:  we do not try to push the bookmark
            :warn:    bookmark is not pushed but warning is printed (can be abort)
            :push:    we try to push the bookmark (doing secret related magic if necessary)
            :promote: old bookmark is promoted to global and pushed//pulled
            :pull:    we update get the bookmark locally



Push behavior:


    secret  |                         |       yes        |
    remote  |               |   yes   |        |   yes   |
    head    |        |  yes |         |        |         |
    ========+=============================================
    current | ignore        | push    | ignore | push*   |
    old     | ignore | warn | promote | ignore | promote |
    local   | ignore        | ignore  | ignore | ignore  |
    global  | push          | push    | ignore | push    |

    * In 2.2 We don't apply secret magic and fail

Pull behavior:

    secret  |                  |       yes        |
    local   |        |   yes   |        |   yes   |
    ========+======================================
    current | pull   | pull    | ignore | pull*   |
    old     | pull   | promote | ignore | promote |
    local   | ignore | ignore  | ignore | ignore  |
    global  | pull   | pull    | ignore | pull    |

    * In 2.2 We don't apply secret magic and fail


clone behavior:

    secret  |          |  yes   |
    ========+===================|
    current |  pull    | ignore |
    old     |  promote | ignore |
    local   |  ignore  | ignore |
    global  |  pull    | ignore | (or pull ?)

    * In 2.2 We don't apply secret magic and fail


Thoughts?

-- 
Pierre-Yves David

http://www.logilab.fr/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20120608/5d1676ac/attachment.pgp>


More information about the Mercurial-devel mailing list