Mercurial equivalent to hg qdiff? - mercurial

mq, which I like a lot, but which I understand is being deprecated in favor of changeset evolution, provides a command hg qdiff that shows the combination of the last-saved patch mixed with the current working directory diffs. I.e., it shows what will be the content of the complete patch if I enter hg commit --amend right now.
Is there a way to show the combined diff like that in base (non-mq) mercurial?

I realized the answer as I prepared to submit the question: hg diff with respect to the parent of the current change:
hg diff -r '.^'

Related

Remote bookmarks in Mercurial to keep new features separate

I'd like to use bookmarks in Mercurial to share new features with other developers. I have followed the basic workflow as they appear here or here. In short:
$ hg bookmark main
$ hg bookmark feature
$ hg update feature
$ hg commit -m "changes"
$ hg push -B feature
My main problem is that at this point my changes are not separate from the default branch, and if someone else does
$ hg pull
$ hg update
in their working directory, they get my changes, too, which is not intended - I would like them to do hg update feature to get them.
I figure if I then commit something (an empty commit maybe) to main and push that as well, all is well and feature appears separate. But is there a better way achieving the same result?
Mercurial knows the special bookmark #. Attach that to a commit which is updated to by default.
See also the wiki, section 5.

Why does "hg status" show changed files when "hg diff -g" doesn't? (One parent)

I have a repository where:
> hg st
shows that my working directory has some uncommitted changes, while
> hg diff
> hg diff -g
> hg diff --git
display nothing.
I read here: 4.10. hg status shows changed files but hg diff doesn't! the following:
hg status reports when file contents or flags have changed relative to either parent. hg diff only reports changed contents relative to the first parent. You can see flag information with the --git option to hg diff and deltas relative to the other parent with -r.
However, if I run hg parents it shows only one parent (the tip). As I mention above, I have also tried hg diff --git and it still displays nothing.
Note:
The above is on Mercurial version 2.0.1
hg status only shows M next to a regular file.
hg diff and hg diff -g print nothing
The filesystem is NFS.
hg parents prints only one parent
Some excerpts from Mercurial in daily use (Mercurial: the definitive guide) (copying here because there seems to be no way to give a convinient link to the end of the page):
The default output of the hg diff command is backwards compatible with the regular diff command, but this has some drawbacks.
The output of hg diff above obscures the fact that we simply renamed a file. The hg diff command accepts an option, --git or -g, to use a newer diff format that displays such information in a more readable form.
This option also helps with a case that can otherwise be confusing: a file that appears to be modified according to hg status, but for which hg diff prints nothing. This situation can arise if we change the file's execute permissions.
The normal diff command pays no attention to file permissions, which is why hg diff prints nothing by default. If we supply it with the -g option, it tells us what really happened.
To summarize, hg diff command misses several kinds of information on changes: attributes, permissions, file names, etc. These changes may exist even if you have a single parent. And hg status correctly takes into account all changes. To see what has happened, use hg diff -g. It's the answer to the question 'what happens'.
Seems like backwards compatibility is the 'why'. I'm not sure, but I suppose that the 'normal diff' is some widespread or built-in Unix/Linux tool (judging from the fact that both hg and git come from that world).
In these situations (it happens a lot to my team), I find that this command will fix about anything:
hg debugrebuilddirstate
or
hg debugrebuilddirstate -r tip
It's lightly documented in the help documentation, but basically I believe it clears out the "dirstate" file which caches information about working-directory files. The next time you hg stat it will refresh it from scratch.
One caveat: if you've added or removed files, that information will be lost when the dirstate is rebuilt.
If you have ignorews or ignoreblanklines set in .hgrc then hg status will show it as changed but hg diff won't (assuming the changes are only whitespace of course).
I just deleted the files that showed up as modified (make a backup if needed) which caused all the files to show up with an ! next to it when I ran
hg st
After that I ran the following command to revert the files (which were already checked in):
hg revert --all --no-backup
and that fixed the problem
In my case something was broken with hg. (same permissions and hg diff -g shows nothing).
I fixed issue with next way:
I cloned repository again in separate folder
I removed everything from this folder except .hg
I moved from old (broken) place everything except .hg to new place
So after this step i have repository which cloned with current version of mercurial + exactly same files.
After this steps i received same (empty) results for commands: hg st and hg diff -g

How to detect that commits are pushable

In Git it is easy, because remote/branch is pointing to a different commit than branch. How to do it with Mercurial?
If you mean seeing what's different between your local repo and the one you're pushing to, try
hg outgoing
Since Mercurial 2.1, there is also a purely local solution: phases. The draft phase is probably what you are looking for. For details, refer to:
https://www.mercurial-scm.org/wiki/Phases
You may find hg phase <rev> and hg log -r "draft()" interesting.
There is an remotebranch extension that will give you a Git-like setup. It tracks the remote heads for the repositories listed in the [paths] and exposes them as tags named <path>/<branch>. This lets you run
$ hg diff -r foo/default
to see what has changed since the default branch in the foo repository. There is also new revset keywords that let you do things like
$ hg log -r "not pushed()"
to get what
$ hg outgoing
would do, but without any network traffic.
What's the command line call to show all revisions in the draft phase?
hg log --style phases
That will display the log + the phase, since Mercurial 2.7 (2013-08-01).
I'd just use hg outgoing as others are suggesting, but hg summary will tell you too. It may require the --remote option to have it check the remote default server.
If you need to select the changesets for further processing, then you can use the outgoing revset predicate. This lets you re-implement hg outgoing as
hg log -r "outgoing()"
but the real benefit is that you can use this in other contexts, such as
hg strip "outgoing()"

Accidentally Working on the Wrong Named Branch in Mercurial

I have been making some changes to my working directory, and noticed that I have accidentally been working on the wrong branch. I have not committed anything yet, and I would like my next commit to go against another branch. What is the best way to do this?
The Shelve extension can give you grief, and this can be done entirely with Mercurial commands. Krtek almost had it but he used export instead of diff. Try this:
hg diff --git > ~/saved-work.patch
hg update --clean desiredbranch
hg import --no-commit ~/saved-work.patch
You should be able to just hg up otherbranch. It is important that you do not use the --clean option to hg up, either directly or via an alias as that will discard your uncommitted changes.
Another option is to use one of the extensions that provides hg shelve. The process would then be:
$ hg shelve --all
$ hg up otherbranch
$ hg unshelve
That will create a patch of your changes within the .hg directory, returning your working directory to a clean state, switch to the 'otherbranch', and then apply the saved patch.
I don't know if it is the best solution, but you can follow these steps :
1° hg diff --git > modifications.patch
2° hg update -C the_right_branch
3° hg patch modifications.patch
Maybe it's better to copy modifications.patch somewhere safe, just in case.
edit: update with diff instead of export. Thanks to the commenters.

How to revert a Mercurial hg pull?

If you do an hg pull and then an hg update (or an hg merge), is there a way to back this out? Ie: revert your repository to the state prior to doing the hg pull?
I believe you can do hg update -r n where you would specify the changeset prior to the pull as n. Though I'm guessing this will still leave the changesets in your repository but this isn't really what we want. ??
hg strip will remove revisions from a repository. Like all powerful commands, its dangerous, so be careful.
https://www.mercurial-scm.org/wiki/StripExtension
Also see:
https://www.mercurial-scm.org/wiki/EditingHistory
If you catch your mistake immediately (or reasonably soon), you can just use hg strip REV to roll back the latest (one or more) changes. ...
Ok, you can't rollback because you've done a commit. What you can do is use 'hg strip' which is part of mq (after 2.8 strip is in it's own extension), or use mq to remove the changes. Either way I suggest you do everything on another clone, just in case.
To do strip, update to a revision that you want to keep, and then
hg strip <REV>
where <REV> is the first revision you want to remove. It will remove that one and all decendents (including your merge commit).
Alternatively you can
hg qnew (if you don't already have a patch queue)
hg qimport <REV>
which will import a single revision into the patch queue. You can then add more, and then use the mq commands to edit, rearrange, delete, or whatever you want to do with those revisions. qdel deletes the current patch.
Edit: Obviously, you'll need to enable the MQ extension for both of these, unless you're using 2.8 or later. In that case strip is in the strip extension, and mq in the mq extension. Both are shipped with the standard installation.
hg --rollback can be used to undo the last transaction so as long as your hg pull is still the most recent transaction then you can use that. This command should be used with care though. See here for some more details.
you can:
hg update -C <version>
see the mercurial FAQ.
If you want to remove all traces of the pull form your history then you need to use an extension as Bert F suggests (the philosophy in mercurial is to never change history)
if you dont mind history containing your mistake you have two slightly different options hg update -C -r which will create a new branch at the version you specify or hg revert -r which will stay on the same branch but create a new uncommited change undoing everything.