Mercurial cherry picking changes for commit

后端 未结 10 1344
长情又很酷
长情又很酷 2020-12-01 01:15

Say, I made many changes to my code and only need to commit a few of those changes. Is there a way to do it in mercurial? I know that darcs has a feature like t

相关标签:
10条回答
  • 2020-12-01 01:43

    Some time has passed. Seems the best option now is hg commit --interactive

    0 讨论(0)
  • 2020-12-01 01:43

    You can use the record extension, which is distributed with Mercurial.

    You need to enable it in your ~/.hgrc file first, by adding it to the [extensions] section:

    [extensions]
    record=
    

    Then, just type hg record instead of hg commit, and you will be able to select which changes to which files you want to commit.

    You can also use the crecord extension which provides a nicer interface to review and select the changes. (It is not distributed with Mercurial, though, and I've seen it occasionally mess up a commit so it's not completely bug-free.)

    0 讨论(0)
  • 2020-12-01 01:46

    Try qct (Qt Commit Tool). It has a "select changes" feature that starts up a 3-way merge tool for you to undo individual changes. After you commit, those changes you "undid" come back.

    0 讨论(0)
  • 2020-12-01 01:47

    MQ as Chad mentioned are one way. There's also more lightweight solutions:

    • Record extension which works roughly the same way as darcs record. It's distributed with mercurial.
    • Shelve extension which allows you to "shelve" certain changes, allowing you to commit only a subset of your changes (the ones that are not shelved)
    0 讨论(0)
  • 2020-12-01 01:48

    The Mercurial Queues tutorial is terrible for this use case. All the examples I have seen assume you have yet to make a commit and you are refreshing a single patch. Most of the time this is not the case, and you have 2 or 3 commits that you want to squash together or change in some other way.

    Lets say you have this sort of history:

    ---O---O---A---B---C
    

    The first example is to squash commits A, B, and C. First init mq:

    $ hg qinit
    

    Now we need to "import" the commits A, B and C into the patch queue. Lets assume they are the last 3 commits. We can use the "-N" revision syntax to import them like so:

    $ hg qimport -r -3:-1
    

    That means import as patches from 3 patches back up to the last commit. You can check the status of these patches with hg qseries. It should show something like this:

    $ hg qseries
    101.diff
    102.diff
    103.diff
    

    Where the numbers 101, 102 and 103 correspond to the local revision numbers of the commits A, B and C. Now these patches are applied, which means the changes that they describe are already in the working copy. You can get rid of the changes the working copy and remove them from the history of commits, saving them in patch form only, by using hg qpop. You can either say hg qpop; hg qpop to pop changes C and B off the stack, or specify a patch to "pop to". In this case, it would be something like this:

    $ hg qpop 101.diff
    now at: 101.diff
    

    You now have the patches for commits B and C in the patch queue, but they are not applied (their changes have been "lost" - they only exist in the patch queue area). Now you can fold these patches into the last one, i.e. we create a new commit that is the equivalent of the sum of the changes A+B+C.

    $ hg qfold -e 102.diff 103.diff
    

    This will show your editor so you can change the commit message. By default the message will be the concatenation of the commit messages for the changes A, B and C, separated by asterisks. The nice thing here is that hg qfold will tab-complete the patches if you are using bash and have the hg-completion script sourced. This leaves the history like this, where A+B+C is a single commit that is the combination of the 3 patches that interest us:

    ---O---O---A+B+C
    

    Another use case is if we have the same sort of history as before, but we want to drop patch B and merge A+C. This is pretty similar to above actually. When you get to the qfold step, you would simply fold in the last commit rather than the last 2 commits:

    $ hg qfold -e 103.diff
    

    This leaves the change for B in the patch queue, but it is not applied to the working copy and its commit is not in the history. You can see this by running:

    $ hg qunapplied
    102.diff
    

    The history now looks like this, where A+C is a single commit that combines changes A and C:

    ---O---O---A+C
    

    A final use case might be that you need to apply only commit C. You'd do this by running the qimport as above, and you would pop off all patches you didn't want:

    $ hg qpop -a
    

    The -a flag means pop off all patches. Now you can apply just the one you do want:

    $ hg qpush 103.diff
    

    This leaves you with this history:

    ---O---O---C
    

    Once you are done with all this, you need to finish off the queue fiddling. This can be done with:

    $ hg qfinish -a
    

    So there we are. You can now run hg push and only commit exactly what you want, or hg email a coherent patch to the mailing list.

    0 讨论(0)
  • 2020-12-01 01:55

    I believe Mercurial Queues fills this role for Mercurial. There's a pretty good tutorial linked there.

    0 讨论(0)
提交回复
热议问题