Perform an empty commit with mercurial

8.2k views Asked by At

With with Mercurial queues extension, I can make an empty commit with some commit message like so:

hg qnew patch_name -m "message"

Is there a way to do this without Mercurial queues? I tried simply:

hg commit -m "message"

but hg just says "nothing changed" and doesn't do the commit, and I don't see any "force" option that would override that.

If you're wondering about my motivation for doing this: we have testing infrastructure where you push to a special repository and it will trigger automated tests to run. You need to put a special string into the commit message of the tipmost commit that says which tests to run. Obviously, I don't want this string in there when I push to the actual repository. Rather than amending the commit twice (once to add the special string, and a second time to remove it), I would find it cleaner to just add an empty commit, and then roll it back -- and I can do this with mq, but I'd like to find a way to do it without mq.

5

There are 5 answers

8
Josef Eisl On

You can use hg commit --amend to create empty commits.

Just create an arbitrary commit and backout the change. Afterwards fold both commits together.

Example:

touch tmp                               # create dummy file
hg add tmp                              # add file and...
hg commit -m "tmp"                      # ... commit
hg rm tmp                               # remove the file again and ...
hg commit --amend -m "empty commit"     # ... commit
4
rpeshkov On

You can make commit that's closing the branch:

hg commit --close-branch -m "message"

Update:

You can close branch once, but it can be reopened with another commit. Simplest way to reopen branch without changing files is to tag some revision. So you can use hg commit --close-branch for empty commit and then hg tag for reopening.

Update v2

Actually you can create new empty commits with just hg tag command. It has -m parameter for setting a commit message. If you don't really care about correctness of this tags, you can use just one tag name by calling hg tag with -f parameter:

hg tag t1 -f -m "message"
0
ThreeStarProgrammer57 On

I just found that hg graft . --force --edit works fine for that purpose.

This will force-graft the current checked-out commit, so it'll be empty, and it'll open an editor to enter a commit message.

1
ecm On

In 2015 a patch to the mercurial-devel mailing list suggested adding an option to the commit command, called --allow-empty (much like the similar git option). However, it was decided to go with a configuration option instead.

This ended up being added in Mercurial 3.5 in 2015 July, by the name ui.allowemptycommit. One doesn't have to specify it in a user's or repo's configuration file however, it is sufficient to add a --config switch to a single command, like this:

hg ci -m "empty commit" --config ui.allowemptycommit=1

Additionally, in 2020 it was suggested for the hg rebase extension command to consider the value of another, experimental configuration option. It is named rewrite.empty-successor, and can be set to either skip (the default) or keep. The configuration option itself was introduced with Mercurial 5.5 in 2020 August, although I am not sure when the rebase extension started to consider it.

How it works seems to be that rebase reads the new option and then locally overrides the older ui.allowemptycommit option depending on whether rewrite.empty-successor is configured to skip or keep. The result is that the rebase extension of older Mercurial versions directly observes the ui.allowemptycommit=1 option (version 4.8.2 tested), while the newer versions' extension observes rewrite.empty-successor=keep instead (version 6.1 tested). The newer versions ignore the external state of the ui.allowemptycommit configuration.

Therefore to get hg rebase to keep empty changesets somewhat portably, both options can be set so as to keep them, like in this example:

hg rebase --config rewrite.empty-successor=keep --config ui.allowemptycommit=1 ...

My use case for all of this is to use hg convert on an svn repo, then use an empty hg commit to become the initial commit (local changeset number 0). Then I will use hg rebase first to make the soon-to-be changeset 0 the parent of the first imported svn revision (so it will become local changeset number 1, matching the svn revision number), and second to fix a certain problematic commit that hg convert doesn't parse correctly. It is crucial to me that the hg rebase commands should keep empty commits, such as those based on svn revisions which only changed directories. (Directories are never tracked by Mercurial on their own, only files.)

1
gremwell On

You can now create empty commits by just doing hg ci -m "empty commit"

e.g.

hg branch my-next-branch
hg ci -m "empty commit"

Will create a my-next-branch with a single empty commit that you can push to the remote repo.