How do I put a bunch of uncommitted changes aside while working on something else

39,791

Solution 1

You have a handful options:

  1. Shelve the items. This saves the changes and removes them from the working directory so the branch can continue. It doesn't create a change-set.

    hg shelve --all --name "UnfinishedChanges"
    
    hg unshelve --name "UnfinishedChanges"
    

    Update/Edit: Newer versions of mercurial may need to use

    hg shelve -n "UnfinishedChanges"
    hg unshelve "UnfinishedChanges"
    

    You can still use --name as an alternative to -n, but mercurial doesn't seem to like --name anymore. Additionally, the --all is no longer required and mercurial will in fact freak out over it.

  2. Patch queue the items using mq. This isn't too dissimilar to shelve in some respects, but behaves differently. The end result is the same, changes are removed and can be optionally re-applied later. When pushed, the patches are logical change-sets, when popped they are saved elsewhere and are not part of change-set history.

    hg qnew "UnfinishedWork"
    hg qrefresh
    hg qpop
    
    hg qpush "UnfinishedWork"
    
  3. Commit them locally, update to the previous change-set and continue working and make use of anonymous branches (or multiple heads). If you then want the changes, you can merge heads. If you don't want the changes, you can strip the change-set.

    hg commit -m"Commiting unfinished work in-line."
    hg update -r<previous revision>
    
    hg strip -r<revision of temporary commit>
    
  4. Commit them to a named branch. The workflow then becomes the same as option 3 - merge or strip when you are ready.

    hg branch "NewBranch"
    hg commit -m"Commiting unfinished work to temporary named branch."
    hg update <previous branch name>
    

Personally I use option 3 or 4 as I don't mind stripping change-sets or checking-in partial code (so long as that doesn't eventually get pushed). This can be used in conjunction with the new Phase stuff to hide your local change-sets from other users if need-be.

I also use the rebase command to move change-sets around to avoid merges where a merge wouldn't add anything to the history of the code. Merges I tend to save for activity between important branches (such as release branches), or activity from a longer-lived feature branch. There is also the histedit command I use for compressing change-sets where the "chattiness" of them reduces the value.

Patch queues are also a common mechanism for doing this, but they have stack semantics. You push and pop patches, but a patch that is "underneath" another patch in the stack requires that the one on top of it be pushed also.

Warning, as with all these options, if the files have more changes since the temporary changes that you've shelved / queued / branched, there will be merge resolution required when un-shelving / pushing / merging.

Solution 2

Personally, I don't like any of the answers posted so far:

  1. I don't like clone branching because I like each project to have only one directory. Working on different directories at the same time completly messes the history of recent files of my editors. I always end up changing the wrong file. So I don't do that anymore.
  2. I use shelve for quick fixes (just to move my uncommited changes to another branch, if I realize I'm at the wrong one). You are talking about days, no way I'd shelve something for days.
  3. I think mq is too complicated for such an ordinary sittuation

I think the best way is to simply commit your changes, than you go back to the changeset before you start these changes and work from there. There are some minor issues, let me illustrate:

Let's say you have the changeset A. Than you start your changes. At this point you want set it aside for a while. First of all, commit your work:

hg ci -m "Working on new stuff"

If you want, you can add a bookmark to make it easier to come back later. I always create bookmarks to my anonymous branches.

hg bookmark new-stuff

Go back to the changeset before these modifications

hg update A

From here, you work and generate the changeset C. Now you have 2 heads (B and C), you'll be warned when you try to push. You can push only one branch by specifying the head of that branch:

hg push -r C

Or you can change the phase of the new-stuff branch to secret. Secret changesets won't be pushed.

hg phase -r new-stuff --secret --force

Solution 3

To keep local uncommited changes, easiest way for me is just to save them as a patch file.

hg diff > /tmp/`hg id -i`.patch

and when you need to return to previous state:

hg up <REV_WHERE_SAVED>
hg patch --no-commit /tmp/<REV_WHERE_SAVED>.patch

Solution 4

You can just clone your repo multiple times. I tend to have a root clone, then multiple childs from there. Example:

  • MyProject.Root
  • MyProject.BugFix1
  • MyProject.BugFix2
  • MyProject.FeatureChange1
  • MyProject.FeatureChange2

The 4 childs are all cloned from the root and push/pull to/from the root. The root then push/pulls from the master repo on the network/internet somewhere. The root acts as your sort of personal staging area.

So in your case, you'd just clone up a new repo and start working. Leave your 'shelved' work alone in the other repo. It's that simple.

The only downside is disk space usage, but if that were a concern you'd not be using DVCS at all anyway ;) Oh and it does kind of pollute your Visual Studio "recent projects" list, but what the hey.

[Edit following comments] :-

To conclude then... what you're doing is completely fine and normal. I would argue it is the best possible way to work when the following are true: 1) it is short-lived 2) you don't need to collaborate with other developers 3) the changes don't need to leave your PC until commit/push time.

Share:
39,791

Related videos on Youtube

Erik
Author by

Erik

I like programming in Ruby on Linux machines.

Updated on June 30, 2020

Comments

  • Erik
    Erik about 4 years

    If I have a bunch of uncommitted changes and want to set it aside while working on something else instead, and then later (f.i. after several days) come back to it and proceed working. What would be the easiest workflow to accomplish this? (So far I have only experience with Mercurial's basic functionality). My usual method was to create a new branch using clone, but there might be better ways.

  • Adam Houldsworth
    Adam Houldsworth almost 12 years
    Any reason for not using branches? This is what they are for and are considerably quicker than repo-cloning.
  • Erik
    Erik almost 12 years
    Thanks for the great answer and helpful examples. Do you happen to know if using hg bookmarks is also an option?
  • Adam Houldsworth
    Adam Houldsworth almost 12 years
    @Erik Possibly, but I have no experience using it.
  • Erik
    Erik almost 12 years
    In my question I stated the following: My usual method was to create a new branch using clone, but there might be better ways.
  • nbevans
    nbevans almost 12 years
    @AdamHouldsworth, technically these are branches... just short lived ones. Making a named branch for a short-lived piece of work is completely stupid. It abuses the purpose named branches which are for long-lived stories of work.
  • Adam Houldsworth
    Adam Houldsworth almost 12 years
    @NathanE If you think named branches for short-lived work is "completely stupid", then there is also anonymous branching, shelving, or the patch queue as other lightweight options. Re-cloning, in my opinion, is equally stupid in the face of other options - it's one potential benefit is having two sets of code open in two VS instances, but I rarely have to do this so using clones as a matter of course doesn't serve me. Just for clarification, I wasn't the downvoter.
  • Adam Houldsworth
    Adam Houldsworth almost 12 years
    @NathanE They are also not exclusive for "long-lived stories of work", that is just something they are good at if you follow continuous integration. Straight from the docs: "Branches occur if lines of development diverge", if you are shelving an item of work to work on something else, this to me sounds like divergence, regardless of how long-lived it is.
  • nbevans
    nbevans almost 12 years
    I frequently have 2 or 3 VS instances open, working on different branches or different clones of branches. It's a big advantage of this technique. I'm well aware of the alternatives and often use Shelving myself but usually when I want to transfer some uncommitted work between two development PCs.
  • nbevans
    nbevans almost 12 years
    Of course they're not exclusive to long-lived stories of work. It's just a best practice that can be ignored. Go ahead and pollute your repo with lots and lots of named branches if you wish :)
  • Erik
    Erik almost 12 years
    @NathanE 'technically these are branches', yes nobody disagrees with that. 'It's a totally legitimate way to use a DVCS', nobody disagrees with that either, in fact I find them very useful. But in the question I asked whether there might be better ways than creating branches using clone. Yet your answer started with: 'You can just clone your repo multiple times.', then you continue with 'So in your case, you'd just clone up a new repo and start working.'. However I was looking for different ways, cloning to separate directories is what I have been doing all along.
  • nbevans
    nbevans almost 12 years
    @Erik, to conclude then... what you're doing is completely fine and normal. I would argue it is the best possible way to work when the following are true: 1) it is short-lived 2) you don't need to collaborate with other developers 3) the changes don't need to leave your PC until commit/push time.
  • Erik
    Erik almost 12 years
    @NathanE I appreciate your conclusion and your help, can you edit your answer with this conclusion, so that I can upvote it?
  • Steve Kaye
    Steve Kaye almost 12 years
    bookmarks can be used to help with option 3 - you can use one to label the revision that you created to stash your change. They can't do the task on their own.
  • Erik
    Erik almost 12 years
    Thanks for the detailed answer! I really like to read people's workflows for those (ordinary?) problems.
  • user247702
    user247702 over 11 years
    @nbevans Making a named branch for a short-lived piece of work is completely stupid. That's simply not true, such a workflow is called topic branching. See here and here for explanations. (The workflow is not limited to Git, by the way.)
  • nbevans
    nbevans over 11 years
    @Stijn You're missing the point of the question. He wants to "set aside" aka "shelve" work so he can work on other stuff. He doesn't want to commit unfinished work to a topic branch. Often when the need arises to make the switch you don't have time to commit anyway, certainly not atomically. My answer still stands and it's a DVCS usage pattern that works in the real world, especially where a developer is having to work on lots of different things at the same time (very common in startups).
  • user247702
    user247702 over 11 years
    I didn't say cloning is wrong, I actually combine cloning and (named) topic branching. I was only refuting your statement about short-lived branches.
  • Norman Gray
    Norman Gray about 10 years
    I think that mq is a bit too complicated for just this situation, but it has a broad enough range of uses, including this one, that it's worth while investing the time to become fluent with it.
  • anatoly techtonik
    anatoly techtonik almost 10 years
    I'd strip /tmp and hg id -i and it will work on Windoze too.
  • anatoly techtonik
    anatoly techtonik almost 10 years
    And hg up is not needed there.
  • mapcuk
    mapcuk almost 10 years
    @techtonik What whould happen if I apply the patch on another revision? Especially if patched files are modified.
  • anatoly techtonik
    anatoly techtonik almost 10 years
    Mercurial will try to merge it, and you'll have to deal with conflict anyway.
  • StayOnTarget
    StayOnTarget about 6 years
    I often use hg share instead of clone because it saves a lot of disk space and is quicker. For anon branches this normally suits my workflow very well.
  • naXa stands with Ukraine
    naXa stands with Ukraine over 5 years
    option --all is not recognized. it's a default behaviour to shelve all changes anyway.
  • Adam Houldsworth
    Adam Houldsworth over 5 years
    @naXa Hi mate, if one of my commands is slightly amiss (maybe because the version has changed), please feel free to edit the answer and I'll approve it if necessary :-)