[PATCH RFC] show: implement "stack" view

Gregory Szorc gregory.szorc at gmail.com
Sun Jul 2 00:06:53 EDT 2017


On Sun, Jun 18, 2017 at 6:53 PM, Augie Fackler <raf at durin42.com> wrote:

> On Sat, Jun 17, 2017 at 01:02:49PM -0600, Gregory Szorc wrote:
> > # HG changeset patch
> > # User Gregory Szorc <gregory.szorc at gmail.com>
> > # Date 1497726059 21600
> > #      Sat Jun 17 13:00:59 2017 -0600
> > # Node ID c9a3d8cdbb925614419216d6e99d9a70f03d926d
> > # Parent  9fcb6df413c9ca475e705ecc15df07584dadb0c1
> > show: implement "stack" view
> >
> > People often want to know what they are working on *now*. As part of
> > this, they also commonly want to know how that work is related to other
> > changesets in the repo so they can perform common actions like rebase,
> > histedit, and merge.
> >
> > `hg show work` made headway into this space. However, it is geared
> > towards a complete repo view as opposed to just the current line of
> > work. If you have a lot of in-flight work or the repo has many heads,
> > the output can be overwhelming. The closest thing Mercurial has to
> > "show me the current thing I'm working on" that doesn't require custom
> > revsets is `hg qseries`. And this requires MQ, which completely changes
> > workflows and repository behavior and has horrible performance on large
> > repos. But as sub-optimal as MQ is, it does some things right, such as
> > expose a model of the repo that is easy for people to reason about.
> > This simplicity is why I think a lot of people prefer to use MQ, despite
> > its shortcomings.
> >
> > One common development workflow is to author a series of linear
> > changesets, using bookmarks, branches, anonymous heads, or even topics
> > (3rd party extension). I'll call this a "stack."
>
> We don't use the term stack yet in Mercurial, other than (oddly
> enough!) the help for MQ. I'm not wholly opposed to coming up with a
> noun for this (stack might even be the right choice), but I think it
> might be worth doing a survey of the existing terms of art for this in
> our features (eg I know patchbomb calls it a series - that might be
> the only other place this is explicitly named right now?)
>

"stack" and "series" are the only options that I can think of. I still like
"stack" because:

a) It is something you can visually relate to. This helps reinforce the
concept of the DAG and that your commits are individual units of work
building on top of each other. A stack is also likely envisioned as
unidirectional - always going up.
b) Durham is pushing a "restack" feature (which I really like) and I think
there is room for `hg show stack` and it to complement each other. They
could potentially agree on the same definition of stack boundaries.


>
> > You periodically
> > rewrite history in place (using `hg histedit`) and reparent the stack
> > against newer changesets (using `hg rebase`). This workflow can be
> > difficult because there is no obvious way to quickly see the current
> > "stack" nor its relation to other changesets. Figuring out arguments to
> > `hg rebase` can be difficult and may require highlighting and pasting
> > multiple changeset nodes to construct a command.
> >
> > The goal of this commit is to make stack based workflows simpler
> > by exposing a view of the current stack and its relationship to
> > other releant changesets, notably the parent of the base changeset
> > in the stack and newer heads that the stack could be rebased or merged
> > into.
> >
> > Introduced is the `hg show stack` view. Essentially, it finds all
> > mutable changesets from the working directory revision in both
> > directions, stopping at a merge or branch point. This limits the
> > revisions to a DAG linear range.
>
> Does this have some affordance so that other extensions
> (remote{names,branches} specifically come to mind) can redefine the
> stack boundary? On Mercurial itself just sniffing for draft changes
> will show a lot of things I don't care about anymore since they're
> pushed upstream. :)
>

I think it makes sense to allow that to be defined, yes. We should be able
to throw it into destutil, just like we have for desthistedit().


>
> >
> > The stack is rendered as a concise list of changesets. Alongside the
> > stack is a visualization of the DAG, similar to `hg log -G`.
>
> Assuming this retains the same lack of BC that we're embracing in `hg
> show`, I'm happy to land something eagerly and iterate (my nagging
> concerns about noun choice aside.)
>

It would. No promise of BC guarantees in `hg show` yet.


>
> [... elided entire implementation, which I didn't read yet ...]
>
> > diff --git a/tests/test-show-stack.t b/tests/test-show-stack.t
> > new file mode 100644
> > --- /dev/null
> > +++ b/tests/test-show-stack.t
> > @@ -0,0 +1,235 @@
> > +  $ cat >> $HGRCPATH << EOF
> > +  > [extensions]
> > +  > show =
> > +  > EOF
> > +
> > +  $ hg init repo0
> > +  $ cd repo0
> > +
> > +Empty repo / no checkout results in error
> > +
> > +  $ hg show stack
> > +  abort: stack view only available when there is a working directory
> > +  [255]
> > +
> > +Stack displays single draft changeset as root revision
> > +
> > +  $ echo 0 > foo
> > +  $ hg -q commit -A -m 'commit 0'
> > +  $ hg show stack
> > +    @  9f171 commit 0
> > +
> > +Stack displays multiple draft changesets
> > +
> > +  $ echo 1 > foo
> > +  $ hg commit -m 'commit 1'
> > +  $ echo 2 > foo
> > +  $ hg commit -m 'commit 2'
> > +  $ echo 3 > foo
> > +  $ hg commit -m 'commit 3'
> > +  $ echo 4 > foo
> > +  $ hg commit -m 'commit 4'
> > +  $ hg show stack
> > +    @  2737b commit 4
> > +    o  d1a69 commit 3
> > +    o  128c8 commit 2
> > +    o  181cc commit 1
> > +    o  9f171 commit 0
> > +
> > +Public parent of draft base is displayed, separated from stack
> > +
> > +  $ hg phase --public -r 0
> > +  $ hg show stack
> > +    @  2737b commit 4
> > +    o  d1a69 commit 3
> > +    o  128c8 commit 2
> > +    o  181cc commit 1
> > +   /   (stack base)
> > +  o  9f171 commit 0
> > +
> > +  $ hg phase --public -r 1
> > +  $ hg show stack
> > +    @  2737b commit 4
> > +    o  d1a69 commit 3
> > +    o  128c8 commit 2
> > +   /   (stack base)
> > +  o  181cc commit 1
> > +
> > +Draft descendants are shown
> > +
> > +  $ hg -q up 2
> > +  $ hg show stack
> > +    o  2737b commit 4
> > +    o  d1a69 commit 3
> > +    @  128c8 commit 2
> > +   /   (stack base)
> > +  o  181cc commit 1
> > +
> > +  $ hg -q up 3
> > +  $ hg show stack
> > +    o  2737b commit 4
> > +    @  d1a69 commit 3
> > +    o  128c8 commit 2
> > +   /   (stack base)
> > +  o  181cc commit 1
> > +
> > +working dir on public changeset should display special message
> > +
> > +  $ hg -q up 1
> > +  $ hg show stack
> > +  (empty stack; working directory is a published changeset)
> > +
> > +Branch point in descendants displayed at top of graph
> > +
> > +  $ hg -q up 3
> > +  $ echo b > foo
> > +  $ hg commit -m 'commit 5 (new dag branch)'
> > +  created new head
> > +  $ hg -q up 2
> > +  $ hg show stack
> > +   \ /  (multiple children)
> > +    |
> > +    o  d1a69 commit 3
> > +    @  128c8 commit 2
> > +   /   (stack base)
> > +  o  181cc commit 1
> > +
> > +  $ cd ..
> > +
> > +Base is stopped at merges
> > +
> > +  $ hg init merge-base
> > +  $ cd merge-base
> > +  $ echo 0 > foo
> > +  $ hg -q commit -A -m initial
> > +  $ echo h1 > foo
> > +  $ hg commit -m 'head 1'
> > +  $ hg -q up 0
> > +  $ echo h2 > foo
> > +  $ hg -q commit -m 'head 2'
> > +  $ hg phase --public -r 0:tip
> > +  $ hg -q up 1
> > +  $ hg merge -t :local 2
> > +  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
> > +  (branch merge, don't forget to commit)
> > +  $ hg commit -m 'merge heads'
> > +
> > +TODO doesn't yet handle case where wdir is a draft merge
> > +
> > +  $ hg show stack
> > +    @  8ee90 merge heads
> > +   /   (stack base)
> > +  o  59478 head 1
> > +
> > +  $ echo d1 > foo
> > +  $ hg commit -m 'draft 1'
> > +  $ echo d2 > foo
> > +  $ hg commit -m 'draft 2'
> > +
> > +  $ hg show stack
> > +    @  430d5 draft 2
> > +    o  787b1 draft 1
> > +   /   (stack base)
> > +  o  8ee90 merge heads
> > +
> > +  $ cd ..
> > +
> > +Now move on to stacks when there are more commits after the base
> branchpoint
> > +
> > +  $ hg init public-rebase
> > +  $ cd public-rebase
> > +  $ echo 0 > foo
> > +  $ hg -q commit -A -m 'base'
> > +  $ hg phase --public -r .
> > +  $ echo d1 > foo
> > +  $ hg commit -m 'draft 1'
> > +  $ echo d2 > foo
> > +  $ hg commit -m 'draft 2'
> > +  $ hg -q up 0
> > +  $ echo 1 > foo
> > +  $ hg commit -m 'new 1'
> > +  created new head
> > +  $ echo 2 > foo
> > +  $ hg commit -m 'new 2'
> > +  $ hg -q up 2
> > +
> > +Newer draft heads don't impact output
> > +
> > +  $ hg show stack
> > +    @  eaffc draft 2
> > +    o  2b218 draft 1
> > +   /   (stack base)
> > +  o  b66bb base
> > +
> > +Newer public heads are rendered
> > +
> > +  $ hg phase --public -r '::tip'
> > +
> > +  $ hg show stack
> > +    (new heads)
> > +
> > +    o  baa4b new 2
> > +   /    (2 commits ahead)
> > +  :
> > +  : (current stack)
> > +  :
> > +  : @  eaffc draft 2
> > +  : o  2b218 draft 1
> > +  :/   (stack base)
> > +  o  b66bb base
> > +
> > +If rebase is available, we show a hint how to rebase to that head
> > +
> > +  $ hg --config extensions.rebase= show stack
> > +    (new heads)
> > +
> > +    o  baa4b new 2
> > +   /    (2 commits ahead)
> > +  :     hg rebase -s 2b218 -d baa4b
> > +  :
> > +  : (current stack)
> > +  :
> > +  : @  eaffc draft 2
> > +  : o  2b218 draft 1
> > +  :/   (stack base)
> > +  o  b66bb base
> > +
> > +Similar tests but for multiple heads
> > +
> > +  $ hg -q up 0
> > +  $ echo h2 > foo
> > +  $ hg -q commit -m 'new head 2'
> > +  $ hg phase --public -r .
> > +  $ hg -q up 2
> > +
> > +  $ hg show stack
> > +    (new heads)
> > +
> > +    o  baa4b new 2
> > +   /    (2 commits ahead)
> > +  : o  9a848 new head 2
> > +  :/    (1 commits ahead)
> > +  :
> > +  : (current stack)
> > +  :
> > +  : @  eaffc draft 2
> > +  : o  2b218 draft 1
> > +  :/   (stack base)
> > +  o  b66bb base
> > +
> > +  $ hg --config extensions.rebase= show stack
> > +    (new heads)
> > +
> > +    o  baa4b new 2
> > +   /    (2 commits ahead)
> > +  :     hg rebase -s 2b218 -d baa4b
> > +  : o  9a848 new head 2
> > +  :/    (1 commits ahead)
> > +  :     hg rebase -s 2b218 -d 9a848
> > +  :
> > +  : (current stack)
> > +  :
> > +  : @  eaffc draft 2
> > +  : o  2b218 draft 1
> > +  :/   (stack base)
> > +  o  b66bb base
> > _______________________________________________
> > Mercurial-devel mailing list
> > Mercurial-devel at mercurial-scm.org
> > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.mercurial-scm.org/pipermail/mercurial-devel/attachments/20170701/777d6cb0/attachment.html>


More information about the Mercurial-devel mailing list