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

5

41

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
Somatist answered 8/12, 2011 at 23:47 Comment(11)
What is the output of hg status?Retail
have you tried running hg diff --git like said in the documentation you posted ?Regorge
hg status shows more than just uncommitted changes, it shows changed files, attributes, existence of files that are not tracked by Mercurial etc. hg diff will show changed contents.Retail
@Regorge Question is, if does make a difference, why does it make difference?Dorty
Make sure to note the hg version: it's still evolving a good bit in semantics.Dorty
@pyfunc, when you said that hg status checks also attributes, and things that hg diff does not show, is there a way to check what is exactly that has changed when hg st shows an M next to the file?.Somatist
I have same symptoms: after cloning the repository with Windows hg on a samba network share, on Linux side hg status shows modified files while hg diff --git shows nothing. File permissions are the same. One parent, freshly updated directory.Northcliffe
I get this a lot, and I've started running hg debugrebuilddirstate which will re-scan and get rid of any fake "m" flags...Haematinic
You should promote 'hg debugrebuilddirstate' to an answer, it fixed my problem when nothing else did!Regional
@ChrisJefferson I think you need to @ Rob to alert him.Somatist
@Rob you're comment is the answer.Ceil
G
22

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).

Gulden answered 9/12, 2011 at 2:22 Comment(7)
I just run into this error again. hg diff and hg diff -g print nothing. hg st show a file as modified (M next to it).Somatist
@intrpc Does hg parents print only one parent? If it prints 2, you have merged and the file might have been modified in both branches, but it is equal upon merging. Or you may simply have changes relative to the scond parent, while diff works only relative to the first one.Gulden
parents prints only one parent. I also upgraded to the latest Hg version (and updated the OP accordingly).Somatist
After confirming none of the files were modified using hg diff -g and hg diff -a, an hg revert reset the status for the files.This was on OS X, the project directory was copied over from a network shareWaverly
Changed execute permissions get me every timeBallon
This does not answer the question - the problem is that (on Linux) hg diff -g shows nothing where hg status shows modified files and where there is no difference in (traditional unix) file permissions. One parent, freshly updated directory.Northcliffe
@PavelGatilov The guide referenced is very helpful for status and diff as well as other basic usage, I wish I'd found it sooner.Bunch
H
10

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.

Haematinic answered 12/6, 2017 at 19:27 Comment(1)
When a WSL1 DrvFS remounted with different fmask and per-file metadata for UNIX permission bits are then enabled for individual tracked files, the state can go wrong. hg debugrebuilddirstate fixes it.Cathodoluminescence
C
5

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).

Cockrell answered 10/12, 2011 at 11:12 Comment(3)
@intrpc Have you checked this?Gulden
Yes. For mercurial 1.8 installed via homebrew on OS 10.6. hg diff even has return status 0.Cockrell
I'm sorry, Ivan, I didn't mean you haven't. I have asked @intrpc (the OP) if he had checked this situation. :)Gulden
I
4

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

Isa answered 16/11, 2015 at 21:30 Comment(1)
This worked for me and is a lot easier than cloning the whole repo again.Tennessee
E
2

In my case something was broken with hg. (same permissions and hg diff -g shows nothing). I fixed issue with next way:

  1. I cloned repository again in separate folder
  2. I removed everything from this folder except .hg
  3. 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

Ezana answered 12/11, 2014 at 16:26 Comment(1)
In fact, the suggestion by RPM works already - deleting the files in question and reverting the changes works, no need for a new clone.Spay

© 2022 - 2024 — McMap. All rights reserved.