Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mercurial: Include secret changesets in bundle?

Using Mercurial, how can I bundle all changesets not known to be in another repository, including secret changesets?

I know bundle's --base option happens to include secret changesets, but I don't want the --base behavior. (And it seems unusually weird that secret changesets are always included with --base but are never included without it. Shouldn't there be a separate option?)

FYI, I commonly want to make a backup of all changesets which are only in my local repo before attempting a potentially dangerous history rewrite.

like image 386
Jon-Eric Avatar asked Mar 09 '12 16:03

Jon-Eric


People also ask

How do I undo a commit in Mercurial?

If you want to revert changes already committed: To backout a specific changeset use hg backout -r CHANGESET . This will prompt you directly with a request for the commit message to use in the backout. To revert a file to a specific changeset, use hg revert -r CHANGESET FILENAME .

What is hg amend?

Adapting the last changeset The easiest and probably one of the most important history editing commands is hg commit --amend . This command doesn't create a completely new changeset. Instead, it takes any new changes in your working directory and combines them with the parent of the working directory.

What hg command saves changes to history?

A quick overview of the basic commands: hg init: create a new repository. hg commit: save your changes in the current repository.


1 Answers

You are correct that hg bundle will normally exclude secret changesets. This is because it's just running the equivalent of hg outgoing and bundling these changesets.

So some work-arounds:

  • If you know that you have at least one draft or public outgoing changeset as an ancestor of your secret changesets, then you can use

    $ hg bundle --base "parents(outgoing())"
    

    to get what you want. The outgoing() revset will pick the missing draft and public changesets and parents(outgoing() will be suitable bases. Since you use --base you get all descendants (public, draft, and secret) from these bases.

  • You could temporarily make your secret changesets draft, bundle, and then mark them secret again:

    $ secret=$(hg log --template "{rev} " -r "secret()"); \
      hg phase -d $secret; \
      hg bundle out.hg; \
      hg phase -f -s $secret
    

    (I use Zsh and there I had to use ${=secret} instead of $secret because Zsh doesn't do word splitting on parameter expansion by default.)

    It's important to chain the commands with ; instead of && since you'll want to reset the phases regardless of what happens in the hg bundle call — passing wrong parameters to hg bundle should not mean that you lose all the information about the secret changesets. Note also that since secret changesets only have secret descendants, there's no information loss with this technique.

    You can turn this into a shell alias:

    [alias]
    bundle-all = !secret=$(hg log --template "{rev} " -r "secret()");
                 hg phase -d $secret;
                 hg bundle $@;
                 hg phase -f -s $secret
    

    The $@ is expanded by Mercurial before the alias is invoked and this lets you insert the necessary arguments for hg bundle.

Note that phase information cannot be stored in bundles — the bundle format has not been changed to accommodate it.

like image 97
Martin Geisler Avatar answered Oct 10 '22 23:10

Martin Geisler