55

During make, I create string fields which I embedded in the linked output. Very useful.

Other than a complex sed/grep parsing of the git status command, how can I easily determine if files in the workspace have been modified according to git?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jamie
  • 7,075
  • 12
  • 56
  • 86
  • If you are only care to know whether something has changed (not which ones have changed) see [How do I programmatically determine if there are uncommited changes?](http://stackoverflow.com/q/3878624/193688) – Chris Johnsen Oct 10 '10 at 06:31

6 Answers6

90

If you just want a plain “Are there any differences from HEAD?”:

git diff-index --quiet HEAD

If the exit code is 0, then there were no differences.

If you want “What files have changed from HEAD?”:

git diff-index --name-only HEAD

If you want “What files have changed from HEAD, and in what ways have they changed (added, deleted, changed)?”:

git diff-index --name-status HEAD

Add -M (and -C) if you want rename (and copy) detection.

These commands will check both the staged contents (what is in the index) and the files in the working tree. Alternatives like git ls-files -m will only check the working tree against the index (i.e. they will disregard any staged (but uncommitted) content that is also in the working tree).

Chris Johnsen
  • 214,407
  • 26
  • 209
  • 186
  • @Jamie This answer should probably be selected as the correct answer. – Christoffer Hammarström Mar 13 '18 at 08:46
  • There’s definitely an edge case where this currently doesn’t work correctly; any idea how to solve it? If you merely `touch` a file, then immediately run `git diff-index HEAD`, that detects the touched file as changed! There seems to be some sort of cache that commands like `git status` first updates, but that `git diff-index` does not. The `git-diff-index` man page says, “The all-zero sha1 means that to get the real diff, you need to look at the object in the working directory directly rather than do an object-to-object diff.” Is there a command that can do that? – andrewdotn Aug 17 '21 at 21:33
  • @andrewdotn Try `git update-index -q --refresh` before *diff-index*. It should update the cached ctime/mtime that is causing the false positive. – Chris Johnsen Aug 18 '21 at 04:50
  • @ChrisJohnsen Thanks. I had a similar problem to andrewdotn's (on files removed then restored by MPFR's autogen.sh), and `git update-index -q --refresh` avoids it (just like `git status`). But I wonder about the meaning of "Looks at the current index and checks to see if merges or updates are needed by checking stat() information." in the git-update-index(1) man page. – vinc17 Mar 29 '22 at 01:15
45

From git help -a:

git ls-files -m
double-beep
  • 5,031
  • 17
  • 33
  • 41
Christoffer Hammarström
  • 27,242
  • 4
  • 49
  • 58
28

git status --porcelain seems to give a nice parsable output.

MDCore
  • 17,583
  • 8
  • 43
  • 48
  • Very nice. Will be useful for other reasons. – Jamie Oct 07 '10 at 16:05
  • That's great, I just used it to automate git commit summaries (like you get from GitHub's web interface) which I actually came to this question looking for: [one-liner to add, commit and push](https://github.com/lmmx/devnotes/wiki/Automated-git-status-summary). – Louis Maddox Apr 25 '15 at 22:22
6

For git hooks, I found this command useful

git diff-index --exit-code --ignore-submodules HEAD

For example

//run some static analysis check that can change the code
something_changed=`git diff-index --exit-code --ignore-submodules HEAD`
if [ -n "$something_changed" ]
then
    echo >&2 "Something changed in $local_ref, not pushing"
    exit 1
fi
Maragues
  • 37,861
  • 14
  • 95
  • 96
  • I like this because it fails the command if there is a change. I am using it on a file that shouldn't change in CI. – nroose Feb 27 '20 at 00:55
5

git diff --name-only does the same (might be more intuitive...)

Yinon Ehrlich
  • 586
  • 6
  • 14
0

An approach with fewer sharp corners:

git diff --quiet HEAD

This appears to do the same thing as the diff-index answer, but with an advantage: it rebuilds the index if necessary, eliminating some flakiness of diff-index. Additionally, diff works correctly when the repository isn't writable by apparently building a temporary index (while diff-index, if the index is stale, will say everything is modified, and the index can't be updated to fix that).