💾 Archived View for ser1.net › post › mercurial-rebase.gmi captured on 2024-03-21 at 15:16:13. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2022-07-16)
-=-=-=-=-=-=-
--------------------------------------------------------------------------------
title: "Mercurial Rebase" date: 2009-07-15T07:06:00Z tags: ["mercurial", "version control system"]
--------------------------------------------------------------------------------
I read Martin Fowler's entry on using mqueues in Mercurial to squash a series of commits[1] into a single commit, and while the post is informative, there's an easier way: the Mercurial rebase[2] command.
1: http://martinfowler.com/bliki/MercurialSquashCommit.html
2: http://mercurial.selenic.com/wiki/RebaseExtension
The rebase extension[3] has been included in Mercurial since 1.3, although it's been available since sometime in the 1.2 release, and can perform a number of useful alterations of a repository. For Martin's use case, his 5-step mqueue sequence is accomplished with two much more simple commands:
3: http://mercurial.selenic.com/wiki/RebaseProject
hg tag "Pre-rebase" hg rebase -s --collapse
The tag is necessary because the rebase command will not operate on descendants or ancestor, and will not automatically create a new tip to hold the rebase. It'd be nice to be able to dispense with the tag, and it isn't necessary if you're (for example) rebasing from a branch onto another branch which already has other changes -- the key point here is that you need to have a different tip that you're rebasing onto which isn't either an ancestor or descendant of the branch that you're rebasing.
Here's a simple use case. First, I'll set up the repository:
% mkdir squash % cd squash % hg init % echo AAA > A % echo BBB > B % echo CCC > C % echo DDD > D % hg addremove adding A adding B adding C adding D % hg ci -m 1 % hg mv A M % hg ci -m 2 % hg mv B N % hg ci -m 3 % hg mv C O % hg ci -m 4 % hg mv D P % hg ci -m 5 % hg glog @ changeset: 4:347a96580b84 | tag: tip | user: Sean Russell | date: Wed Jul 15 07:26:40 2009 -0400 | summary: 5 | o changeset: 3:e1e2c4e27fcf | user: Sean Russell | date: Wed Jul 15 07:26:34 2009 -0400 | summary: 4 | o changeset: 2:47b3a7f41d78 | user: Sean Russell | date: Wed Jul 15 07:26:28 2009 -0400 | summary: 3 | o changeset: 1:e0879f674e71 | user: Sean Russell | date: Wed Jul 15 07:26:24 2009 -0400 | summary: 2 | o changeset: 0:2902dfa1725a user: Sean Russell date: Wed Jul 15 07:26:12 2009 -0400 summary: 1
Here's the actual rebase. First, switch to the revision that you want to rebase [onto]{style="font-style: italic;"}, then create a tag to create a new tip, then perform the rebase. In this example, I want to collapse revisions 1-4, so I switch to revision 0:
% hg up 0 4 files updated, 0 files merged, 4 files removed, 0 files unresolved % hg tag Pre-collapse % hg rebase -s 1 --collapse saving bundle to /home/ser/squash/.hg/strip-backup/e0879f674e71-temp adding branch adding changesets adding manifests adding file changes added 2 changesets with 5 changes to 5 files rebase completed % hg glog @ changeset: 2:3420d5add3eb | tag: tip | user: Sean Russell | date: Wed Jul 15 07:26:40 2009 -0400 | summary: Collapsed revision | o changeset: 1:a98523a2e8f9 | user: Sean Russell | date: Wed Jul 15 07:26:50 2009 -0400 | summary: Added tag Pre-collapse for changeset 2902dfa1725a | o changeset: 0:2902dfa1725a | tag: Pre-collapse | user: Sean Russell | date: Wed Jul 15 07:26:12 2009 -0400 | summary: 1
The rebase command is quite useful, and the rebase page gives examples of a number of use cases. For cases like this, it's much easier than using the raw mqueue operations upon which it is based.