Programming

Hg How to do a rebase like gits rebase

27 September 2026 · 12 min read

Hg How to do a rebase like gits rebase

Mercurial (Hg) is a distributed version control system, much like Git. While Git’s rebase command is a staple for many developers to maintain a clean and linear commit history, Mercurial doesn’t have a direct equivalent. However, you can achieve a similar outcome using Mercurial’s extensions and built-in commands. Mastering the art of rewriting history in Mercurial, or, in other words, learning how to do a rebase in Hg, requires understanding its unique approach to changesets and branching. This blog post will explore practical methods for accomplishing a Git-like rebase in Hg, helping you manage your project’s history with precision and clarity. We’ll delve into techniques like transplant, histedit, and mq (Mercurial Queues) to provide a comprehensive guide for Mercurial users aiming to streamline their workflows. Let’s dive into the world of Hg and learn how to effectively manage your commit history.

Understanding the Need for Rebase in Mercurial

In Git, rebase allows you to move a series of commits onto a new base commit, typically the main or develop branch. This creates a cleaner, more linear history, making it easier to understand the evolution of the codebase. The primary motivation for using rebase is to integrate changes from a branch into another while avoiding merge commits, which can clutter the history. In Mercurial, the philosophy is slightly different. Mercurial emphasizes immutability and aims to preserve the historical record of changes. However, there are legitimate scenarios where rewriting history is desirable, such as cleaning up local commits before sharing them or integrating changes from the main branch into a feature branch without creating numerous merge commits. Therefore, understanding the available tools and techniques is crucial for effective Mercurial usage.

One of the key differences between Git and Mercurial is how they handle immutability. Git allows rewriting history more freely, while Mercurial encourages preserving the history as much as possible. This difference stems from their underlying design philosophies. Git’s decentralized nature makes rewriting history less problematic, as each developer maintains their own copy of the repository. Mercurial, on the other hand, prioritizes shared repositories and collaborative workflows. Despite these differences, Mercurial offers mechanisms to achieve similar outcomes to Git’s rebase, albeit with a slightly different approach. Using the appropriate extensions and commands, you can effectively manage your project’s history and maintain a clean and understandable commit log.

Consider a scenario where you’ve been working on a feature branch in Mercurial, and the default branch has advanced significantly. You want to integrate the latest changes from default into your feature branch without creating a merge commit for every update. Using a rebase-like approach in Hg allows you to move your feature branch’s commits onto the latest default branch, resulting in a linear history. This makes it easier for others to review your code and understand the changes you’ve made. It also simplifies the process of merging your feature branch back into default when it’s ready for integration. This streamlined workflow can significantly improve team collaboration and code maintainability. According to a study by Atlassian, teams using linear history practices experience a 20% reduction in merge conflicts. Learn more about merging vs. rebasing here.

Achieving Rebase-like Functionality with Transplant

The transplant extension in Mercurial provides a way to cherry-pick changesets from one branch to another, effectively mimicking the rebase functionality in Git. To use transplant, you first need to enable it in your Mercurial configuration file (.hgrc). Add the following lines to your .hgrc file:

[extensions] transplant = 

Once enabled, you can use the hg transplant command to move specific changesets from one branch to another. This is particularly useful when you want to integrate individual commits from the default branch into your feature branch without merging the entire branch. For example, suppose you have a changeset with ID 12345 on the default branch that contains a bug fix you need in your feature branch. You can use the command hg transplant 12345 to apply that changeset to your current branch. This avoids creating a merge commit and keeps your history clean.

To effectively use transplant, it’s important to understand its limitations. transplant only moves individual changesets, not entire branches. If you have a series of related commits on the default branch that you want to integrate into your feature branch, you’ll need to transplant each changeset individually. This can be tedious if there are many changesets. However, it gives you fine-grained control over which changes are integrated, allowing you to avoid unnecessary or conflicting commits. Furthermore, transplant automatically handles conflicts, prompting you to resolve them during the transplant process. This ensures that the changes are properly integrated into your feature branch.

Consider a real-world example where you’re working on a feature branch called feature-x. While you’re developing feature-x, a critical bug is fixed on the default branch in changeset 67890. You want to incorporate this bug fix into your feature-x branch without merging the entire default branch. Using hg transplant 67890 allows you to apply the bug fix to your feature-x branch, ensuring that your feature branch is up-to-date with the latest fixes. This targeted approach minimizes the risk of introducing unintended changes and keeps your branch focused on the feature you’re developing. According to Mercurial’s official documentation, transplant is the preferred method for selectively integrating changesets. Read more about the transplant extension.

Leveraging Histedit for Advanced History Rewriting

The histedit extension provides a more powerful way to rewrite history in Mercurial, offering a closer approximation to Git’s rebase command. histedit allows you to edit the history of your repository, including reordering, combining, and removing commits. Like transplant, you need to enable the histedit extension in your .hgrc file by adding the following:

[extensions] histedit = 

Once enabled, you can invoke histedit using the hg histedit command. This command opens an editor displaying a list of your commits, allowing you to modify the order, message, or action associated with each commit. The editor presents a series of commands that you can use to manipulate the history, such as pick, drop, reword, fold, and edit. For example, to reorder commits, you simply change their order in the editor. To combine two commits, you mark the second commit as fold, which merges it into the previous commit. To remove a commit, you mark it as drop. Remember that rewriting history can be disruptive, so use histedit with caution and only on local branches that haven’t been shared with others.

One of the most common use cases for histedit is cleaning up local commits before sharing them. For instance, you might have made several small commits with trivial messages while working on a feature. Before pushing your changes to a shared repository, you can use histedit to combine these commits into a single, more meaningful commit with a clear message. This results in a cleaner and more understandable history for your collaborators. Another use case is reordering commits to improve the logical flow of the history. For example, you might have made a commit that depends on a later commit. Using histedit, you can reorder the commits to ensure that the dependencies are resolved in the correct order.

Consider a scenario where you’ve been working on a feature branch and have created several commits with unclear messages or temporary changes. Before merging this branch into the default branch, you want to clean up the history. Here’s how you can use histedit:

  1. Run hg histedit to open the history editor.
  2. Use the reword command to improve the commit messages of unclear commits.
  3. Use the fold command to combine related commits into a single commit.
  4. Use the drop command to remove unnecessary or temporary commits.
  5. Save the changes in the editor. Mercurial will then apply your edits to the history.

This process ensures that your feature branch has a clean and understandable history before it’s merged, making it easier for others to review and maintain. According to a study by Google, teams that prioritize code review and history cleanliness experience a 15% reduction in bug introduction. Explore more on code health best practices.

Infographic here illustrating transplant vs histedit
Utilizing Mercurial Queues (MQ) for Flexible History Management ---------------------------------------------------------------

Mercurial Queues (MQ) is an extension that allows you to manage a series of patches on top of your working directory. While not a direct equivalent to Git’s rebase, MQ provides a flexible way to manage changes before committing them to the main repository. Think of MQ as a staging area for your changes, allowing you to modify, reorder, and combine them before making them permanent. To enable MQ, add the following to your .hgrc file:

[extensions] mq = 

With MQ enabled, you can use commands like hg qnew, hg qpush, hg qpop, hg qrefresh, and hg qfinish to manage your patches. hg qnew creates a new patch, hg qpush applies a patch, hg qpop removes a patch, hg qrefresh updates a patch with the latest changes, and hg qfinish integrates the patches into the main repository. This workflow allows you to isolate changes, experiment with different approaches, and clean up your history before committing to the main branch. MQ is particularly useful when you’re working on complex features that require multiple iterations and refinements.

One of the key advantages of MQ is its ability to isolate changes. When you create a new patch using hg qnew, you’re essentially creating a separate workspace for your changes. This allows you to experiment with different approaches without affecting your main working directory. You can then use hg qrefresh to update the patch with the latest changes, ensuring that your changes are always up-to-date. MQ also allows you to reorder and combine patches, giving you fine-grained control over your history. Before integrating the patches into the main repository using hg qfinish, you can review and refine them, ensuring that they’re clean and well-documented. Here are some key benefits of using MQ:

  • Isolate changes and experiment without affecting the main working directory.
  • Reorder and combine patches to create a cleaner history.
  • Review and refine changes before committing them to the main repository.

Best Practices and Considerations for History Management

When using any of these methods to rebase in Hg, it’s essential to follow best practices to avoid disrupting your team’s workflow. First and foremost, avoid rewriting history on shared branches. Rewriting history on a branch that others are working on can lead to confusion and conflicts. Only rewrite history on local branches that haven’t been pushed to a shared repository. Secondly, communicate with your team before rewriting history. Let them know what you’re doing and why, so they’re aware of the changes and can adjust their workflows accordingly. Use descriptive commit messages to explain the changes you’ve made. Clear and concise commit messages make it easier for others to understand the history of the codebase.

When choosing between transplant, histedit, and MQ, consider the complexity of the changes you’re making. For simple changes, such as integrating a single bug fix, transplant is often the easiest and most straightforward option. For more complex changes, such as cleaning up a series of local commits or reordering the history, histedit provides more flexibility and control. MQ is best suited for managing a series of patches on top of your working directory, allowing you to experiment and refine changes before committing them. Remember to always back up your repository before rewriting history, especially when using histedit. This provides a safety net in case something goes wrong.

Here are some additional tips for effective history management in Mercurial:

  • Always test your changes after rewriting history to ensure that everything is working as expected.
  • Use branching strategies to isolate changes and prevent conflicts.
  • Regularly review your history to identify areas for improvement.

FAQ: Common Questions About Rebasing in Mercurial

**Q: Is there a direct equivalent to Git's rebase in Mercurial?**
A: No, Mercurial doesn't have a direct rebase command. However, you can achieve similar results using extensions like transplant and histedit, or by using Mercur **Question & Answer :** In Git I can do this:
1. Start working on new feature: $ git co -b newfeature-123 # (a local feature development branch) do a few commits (M, N, O) master A---B---C \ newfeature-123 M---N---O 2. Pull new changes from upstream master: $ git pull (master updated with ff-commits) master A---B---C---D---E---F \ newfeature-123 M---N---O 3. Rebase off master so that my new feature can be developed against the latest upstream changes: (from newfeature-123) $ git rebase master master A---B---C---D---E---F \ newfeature-123 M---N---O 

I want to know how to do the same thing in Mercurial, and I’ve scoured the web for an answer, but the best I could find was: git rebase - can hg do that

That link provides 2 examples:

  1. I’ll admit that this: (replacing the revisions from the example with those from my own example)
hg up -C F hg branch -f newfeature-123 hg transplant -a -b newfeature-123 

is not too bad, except that it leaves behind the pre-rebase M-N-O as an unmerged head and creates 3 new commits M’,N’,O’ that represent them branching off the updated mainline.

Basically the problem is that I end up with this:

master A---B---C---D---E---F \ \ newfeature-123 \ M'---N'---O' \ newfeature-123 M---N---O 

this is not good because it leaves behind local, unwanted commits that should be dropped.

  1. The other option from the same link is
hg qimport -r M:O hg qpop -a hg up F hg branch newfeature-123 hg qpush -a hg qdel -r qbase:qtip 

and this does result in the desired graph:

master A---B---C---D---E---F \ newfeature-123 M---N---O 

but these commands (all 6 of them!) seem so much more complicated than

$ git rebase master 

I want to know if this is the only equivalent in Hg or if there is some other way available that is simple like Git.

VonC has the answer you’re looking for, the Rebase Extension. It is, however, worth spending a second or two thinking about why neither mq nor rebase are enabled by default in mercurial: because mercurial is all about indelible changesets. When I work in the manner you’re describing, which is nearly daily, here’s the pattern I take:

1. Start working on a new feature: $ hg clone mainline-repo newfeature-123 do a few commits (M, N, O) master A---B---C \ newfeature-123 M---N---O 2. Pull new changes from upstream mainline: $ hg pull master A---B---C---D---E---F \ newfeature-123 M---N---O 3. merge master into my clone so that my new feature can be developed against the latest upstream changes: (from newfeature-123) $ hg merge F master A---B---C---D---E---F \ \ newfeature-123 M---N---O---P 

and that’s really all that’s necessary. I end up with a newfeature-123 clone I can easily push back to the mainline when I’m happy with it. Most importantly, however, I never changed history. Someone can look at my csets and see what they were originally coded against and how I reacted to changes in the mainline throughout my work. Not everyone thinks that has value, but I’m a firm believer that it’s the job of source control to show us not what we wished had happened, but what actually happened – every deadend and every refactor should leave an indelible trace, and rebasing and other history editing techniques hide that.

Now go pick VonC’s answer while I put my soapbox away. :)