== Concatenating multiple changesets into one == (See also: [[EditingHistory]], [[HisteditExtension]] (which provides an editor-driven UI for this), [[CollapseExtension]], [[RebaseProject]] (section ''Collapsing'')). === Problem === Suppose you want to concatenate the last k changesets of a [[Repository|repository]] {{{#!dot digraph { rankdir = LR; node [shape=box]; S -> "S+1" -> "S+2"; "S+2" -> "S+k" [style=dashed]; label="oldrepo" }}} into a single, combined changeset {{{#!dot digraph { rankdir = LR; node [shape=box]; S -> "S+k (combined)" label="newrepo" }}} === Revert solution (using hg only) === Execute the following steps: '''~+{{{1: hg -R oldrepo update S}}}+~''' This [[Update|updates]] the [[WorkingDirectory|working directory]] to revision S. Specifically, this means that the contents of the working directory are changed to that of revision S, and that S becomes the parent of the working directory. '''~+{{{2: hg -R oldrepo revert -r tip --all}}}+~''' {{{#!dot digraph { rankdir = LR; node [shape=box]; "working directory" -> S [label="1. update"]; S -> "S+1" -> "S+2"; "S+2" -> "S+k" [style=dashed]; "working directory" -> "S+k" [color=red label="2. revert"]; "working directory" [shape=ellipse]; label="oldrepo" }}} This [[Revert|reverts]] the working directory to its contents at [[Tip|tip]]. Since the parent of the working directory is still S, this means that the combined contents of all changesets between S and S+k show up as the modifications in the working directory. /!\ Revert does not preserve copy and move history. '''~+{{{3: hg -R oldrepo commit -m "Combine changesets S+1..S+k"}}}+~''' {{{#!dot digraph { rankdir = LR; node [shape=box]; "working directory" -> "S+k (combined)" [color=red label="3. commit"]; "working directory" -> S [style=invis]; S -> "S+k (combined)"; S -> "S+1" -> "S+2"; "S+2" -> "S+k" [style=dashed]; "working directory" [shape=ellipse]; label="oldrepo" }}} Committing these modifications creates a new changeset "S+k (combined)", containing combined changesets S+1 to S+k. '''~+{{{4: hg clone -r tip oldrepo newrepo}}}+~''' {{{#!dot digraph { rankdir = LR; node [shape=box]; "working directory" -> S [style=invis]; "working directory" -> "S+k (combined)" [color=red label="4. clone -r tip"] S -> "S+k (combined)" "working directory" [shape=ellipse label="cloned working directory"] label="newrepo" }}} <
>This assumes you want to get rid of your individual changesets (which are a dangling [[Branch|branch]] in oldrepo) and just keep the combined changeset. newrepo will now just have the combined changeset. /!\ This will strip out '''all''' other branches, not just the one dangling branch ''that you don't want.'' If you have other branches that you want to keep, specify their [[Head|head]] revisions or [[NamedBranches|branch names]] on the clone call: {{{hg clone -r tip -r branch1 -r branch2 -r branch3 oldrepo newrepo}}} Or you can use the {{{strip}}} command provided by the [[MqExtension|Mercurial Queues Extension]]. Note that if you're planning to use mq, there's a much more convenient way to do the above... === Patch solution (using hg only) === Make a patch containing the changesets you want to concatenate. <
> '''~+{{{1: hg -R oldrepo export --git -r S:tip > patchfile}}}+~''' Make a partial clone of the repository, up to and including the parent of S. This discards the patch changesets. <
> '''~+{{{2: hg clone -r "p1(S)" oldrepo newrepo}}}+~''' Import the patch in the cloned repository as one changeset. <
> '''~+{{{3: hg -R newrepo import -m "Combine changesets S+1..S+k" patchfile}}}+~''' === Patch queue solution (using mq) === Integrate the changesets you want to concatenate in a patch queue (verify you don't have pending patches there using {{{hg qseries}}}). <
> '''~+{{{1: hg qimport -r S+1:tip}}}+~''' (note how the start of the commit range specified is the fist commit we want to squash: S+1) Pop all the patches but the first. <
> '''~+{{{2: hg qgoto qbase}}}+~''' "Fold" unapplied patches, i.e. concatenate changesets. <
> '''~+{{{3: hg qfold $(hg qunapp)}}}+~''' <
> '''~+{{{3: for /F %i in ('hg qunapp') do hg qfold %i (Windows)}}}+~''' <
> This has the big advantage over the previous method that the commit messages will also be concatenated (separated by the {{{* * *}}} string). You can see the message using {{{hg qhead}}} and edit it using {{{hg qrefresh -e}}}. Reintegrate the folded patch in the repository. <
> '''~+{{{4: hg qfinish qbase}}}+~''' <
> {{{tip}}} is now the concatenation of former changesets {{{S:tip}}}. There's no extra branch left, therefore no additional cleanup to do. ---- CategoryTipsAndTricks