Mark Needham

Thoughts on Software Development

Mercurial: Only pushing some local changes

with 8 comments

One problem we’ve come across a few times over the last couple of months while using Mercurial is the situation where we want to quickly commit a local change without committing other local changes that we’ve made.

The example we came across today was where we wanted to make a change to the build file as we’d made a mistake in the target that runs on our continuous integration server and hadn’t noticed for a while during which time we’d accumulated other local changes.

The following is a rough diagram of the situation we had:


We had multiple file changes in our working directory which hadn’t yet been checked in to the local repository or the central repository.

We wanted to push just the change in blue.

My initial thought was that I could check in just that one file into our local repository and then push it to the central one.

hg ci -m "mark: updating build file to fix build" -A /path/to/build.file

I then wanted to push that change but when I went to do so I realised that they were other incoming changes which we hadn’t yet integrated with.

In order to integrate with those changes we need to make sure that we don’t have any locally uncommitted changes which of course in this scenario we do since we deliberately chose not to check in some of our local changes.

One way around this would be to just force the push and ignore the need to integrate with the remote changes but that doesn’t seem the right approach to me but I’m not sure what is.

We ended up just checking in everything we had locally, commenting out the bits that we were currently working on, merging with the remote changes and then pushing everything to the remote repository.

That’s obviously a really poor way of solving the problem so I’d be interested in what a good way to solve this problem would be!

Be Sociable, Share!

Written by Mark Needham

June 25th, 2010 at 11:32 pm

Posted in Version Control

Tagged with

  • In this case, if I’m using the bookmark-rebase workflow to mimic Git’s local branches, then a pull –rebase to master will bring upstream changes down to the master branch, and my topic branch is completely unaffected. Next, I’ll commit both changes, one at a time, to my topic branch. Finally, you can use “hg transplant” to cherrypick that one commit and replay it onto master.

    Now you have that commit on the master branch, and you can continue on your way with your topic branch. You can push the master branch with “hg push -b master”, so your topic branch stays local. This is a fairly common workflow in git, I usually look to see how to do it in git, then translate that workflow into the various available hg extensions.

  • Srushti

    If you were using git I would have suggested a “git stash”. I did some research and it doesn’t look like hg has a stash equivalent. So, you’d probably have to something like “hg diff > stash && hg revert –all –no-backup” and then patch them in once you were done pushing.

  • @Srushti – oh yeh I forgot about stash! That option is certainly available in TortoiseHg but it’s called Shelve –

    WIll give that a try next time.

  • Mike

    You could also use a patch queue. If you use tortoisehg, this is really easy.

    Assuming you have mq enabled, tortoise commit dialog will have option for new patch bender name, and commit changes to anew.

    Deselect files don’t want in the patch. Commit. Then do a new name, commit remaining changes.

    Unapply last patch that contains changes you don’t want to commit yet.

    Finalze patch with build changes, push to central.

    Reapply patch with changes and continue work.

    If you don’t want to deal with queues anymore, use commit dialog. Unselect all files and do refresh. This empties patch

    To get rid of patch, unfortunately have to resort to cmd line. Hg pop -f to remove patch. -f does pop even though there are local change.

    Mq is well worth learning.

  • You could check in the isolated change locally, clone the local repo to local-repo-2, integrate the incoming changes in local-repo-2 and then push from there into the remote repo.

  • Gonzalo Casas

    The proper solution is probably use of Mercurial Queues, as Mike pointed out already. I was pretty skeptical about using MQ in the past, fearing it would add too much complexity to our workflow, but indeed, it does not, and it simplifies a lot many of our everyday tasks.

    As a cheap alternative, in this case you could have committed locally, export the patch, and mail it to a coworker for the push… 🙂

  • Arun

    You are missing git stash in Mercurial 🙂

  • newbie

    This is a newbie question, but what’s wrong with the following sequence in this case:

    hg pull -u
    hg rebase
    hg commit path/to/build.file