[PATCH] graft: introduce --base option for using custom base revision for merge
Augie Fackler
raf at durin42.com
Sat Oct 13 06:55:51 EDT 2018
> On Oct 13, 2018, at 12:02, Mads Kiilerich <mads at kiilerich.com> wrote:
>
> # HG changeset patch
> # User Mads Kiilerich <mads at kiilerich.com>
> # Date 1539424786 -7200
> # Sat Oct 13 11:59:46 2018 +0200
> # Node ID 167e7e7bbead47fadfe4072143cc53b409e3d8b9
> # Parent 38ac525b44c93fcadb3680d4ded56f1e5a0029b2
> graft: introduce --base option for using custom base revision for merge
>
> The graft command usually merges with the graft revision using its p1 as base
> for the merge.
>
> As a trivial extension of this, we introduce the --base option to allow for
> using another base revision.
>
> This can be used as a building block for grafting and collapsing multiple
> changesets at once, or for grafting the resulting change from a merge as a
> single simple change. (This is kind of similar to backout --parent ... only
> different: it must be an ancestor, but is usually *not* a parent.)
>
> This is probably an advanced use case, and we do thus not show it in the
> non-verbose help.
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -2223,6 +2223,7 @@ def forget(ui, repo, *pats, **opts):
> @command(
> 'graft',
> [('r', 'rev', [], _('revisions to graft'), _('REV')),
> + ('', 'base', '', _('base revision when doing the graft merge'), _('REV')),
> ('c', 'continue', False, _('resume interrupted graft')),
> ('', 'stop', False, _('stop interrupted graft')),
> ('', 'abort', False, _('abort interrupted graft')),
> @@ -2267,6 +2268,12 @@ def graft(ui, repo, *revs, **opts):
>
> .. container:: verbose
>
> + The --base option can be used to specify another merge base than the
> + first parent, thus allowing graft of the impact of a merge, or
> + collapsing of multiple changesets.
Perhaps:
---
The --base option can be used to backport the result of a merge as a single commit ....
(example command)
--base can also be used to back out a commit like this:
(example command)
--base is flexible enough other interesting operations are possible. Please consider sending patches to document other useful operations.
---
or something like that. Does that get you started?
> +
> + .. container:: verbose
> +
> Examples:
>
> - copy a single change to the stable branch and edit its description::
> @@ -2305,6 +2312,9 @@ def _dograft(ui, repo, *revs, **opts):
>
> revs = list(revs)
> revs.extend(opts.get('rev'))
> + basectx = None
> + if opts.get('base'):
> + basectx = scmutil.revsingle(repo, opts['base'], None)
> # a dict of data to be stored in state file
> statedata = {}
> # list of new nodes created by ongoing graft
> @@ -2384,13 +2394,16 @@ def _dograft(ui, repo, *revs, **opts):
> revs = scmutil.revrange(repo, revs)
>
> skipped = set()
> - # check for merges
> - for rev in repo.revs('%ld and merge()', revs):
> - ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
> - skipped.add(rev)
> + if basectx is None:
> + # check for merges
> + for rev in repo.revs('%ld and merge()', revs):
> + ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
> + skipped.add(rev)
> revs = [r for r in revs if r not in skipped]
> if not revs:
> return -1
> + if basectx is not None and len(revs) != 1:
> + raise error.Abort(_('only one revision allowed with --base '))
>
> # Don't check in the --continue case, in effect retaining --force across
> # --continues. That's because without --force, any revisions we decided to
> @@ -2398,7 +2411,7 @@ def _dograft(ui, repo, *revs, **opts):
> # way to the graftstate. With --force, any revisions we would have otherwise
> # skipped would not have been filtered out, and if they hadn't been applied
> # already, they'd have been in the graftstate.
> - if not (cont or opts.get('force')):
> + if not (cont or opts.get('force')) and basectx is None:
> # check for ancestors of dest branch
> crev = repo['.'].rev()
> ancestors = repo.changelog.ancestors([crev], inclusive=True)
> @@ -2494,8 +2507,9 @@ def _dograft(ui, repo, *revs, **opts):
> if not cont:
> # perform the graft merge with p1(rev) as 'ancestor'
> overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
> + base = ctx.p1() if basectx is None else basectx
> with ui.configoverride(overrides, 'graft'):
> - stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'graft'])
> + stats = mergemod.graft(repo, ctx, base, ['local', 'graft'])
> # report any conflicts
> if stats.unresolvedcount > 0:
> # write out state for --continue
> diff --git a/tests/test-completion.t b/tests/test-completion.t
> --- a/tests/test-completion.t
> +++ b/tests/test-completion.t
> @@ -318,7 +318,7 @@ Show all commands + options
> debugwireargs: three, four, five, ssh, remotecmd, insecure
> debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
> files: rev, print0, include, exclude, template, subrepos
> - graft: rev, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
> + graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
> grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
> heads: rev, topo, active, closed, style, template
> help: extension, command, keyword, system
> diff --git a/tests/test-graft.t b/tests/test-graft.t
> --- a/tests/test-graft.t
> +++ b/tests/test-graft.t
> @@ -25,7 +25,7 @@ Create a repo with some stuff in it:
> $ echo b > e
> $ hg branch -q stable
> $ hg ci -m5
> - $ hg merge -q default --tool internal:local
> + $ hg merge -q default --tool internal:local # for conflicts in e, choose 5 and ignore 4
> $ hg branch -q default
> $ hg ci -m6
> $ hg phase --public 3
> @@ -46,8 +46,34 @@ Create a repo with some stuff in it:
> |
> o test at 0.public: 0
>
> +Test --base for grafting the merge of 4 from the perspective of 5, thus only getting the change to d
> +
> + $ hg up -cqr 3
> + $ hg graft -r 6 --base 5
> + grafting 6:25a2b029d3ae "6" (tip)
> + merging e
> + $ hg st --change .
> + M d
> +
> + $ hg -q strip . --config extensions.strip=
> +
> +Test --base for collapsing changesets 2 and 3, thus getting both b and c
> +
> + $ hg up -cqr 0
> + $ hg graft -r 3 --base 1
> + grafting 3:4c60f11aa304 "3"
> + merging a and b to b
> + merging a and c to c
> + $ hg st --change .
> + A b
> + A c
> + R a
> +
> + $ hg -q strip . --config extensions.strip=
> +
> Can't continue without starting:
>
> + $ hg -q up -cr tip
> $ hg rm -q e
> $ hg graft --continue
> abort: no graft in progress
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list