Skip to content

Instantly share code, notes, and snippets.

@sindresorhus
Created October 16, 2012 11:20
Show Gist options
  • Star 60 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sindresorhus/3898739 to your computer and use it in GitHub Desktop.
Save sindresorhus/3898739 to your computer and use it in GitHub Desktop.
Benchmark results of the fastest way to check if a git branch is dirty

Tested against the WebKit git repo by entering the repo with 1 file dirty.


git diff --quiet --ignore-submodules HEAD # Will tell if there are any uncomitted changes, staged or not.
0.6 sec

git diff-index --quiet HEAD # Only tracked
2 sec

git diff --shortstat
8.2 sec

git status --porcelain
42 sec

zstyle ':vcs_info:*' check-for-changes true
50 sec

@ericbn
Copy link

ericbn commented Oct 14, 2016

Unless you want to take untracked files into account too. The best I've come up with is:

git diff-files --no-ext-diff --quiet || git diff-index --no-ext-diff --quiet --cached HEAD

This is the benchmark I got in a NFS filesystem with the WebKit repo clean:

Command Real time (secs)
git ls-files --other --exclude-standard (lists untracked files) 2.756
git status --porcelain (lists indexed, unindexed and untracked files) 2.313
git diff-index --no-ext-diff --quiet --cached HEAD (checks indexed files) 0.317
git diff-files --no-ext-diff --quiet (checks unindexed files) 0.022

@nh2
Copy link

nh2 commented Dec 24, 2020

git diff-index --quiet HEAD -- can return outdated information unless you run git update-index -q --refresh (or a non-plumbing git status) first, (see https://stackoverflow.com/questions/2657935/checking-for-a-dirty-index-or-untracked-files-with-git/2659808#comment28747279_2659808) so it's not a fair comparison vs git status --porcelain without that.

Also any use of git diff-index --no-ext-diff --quiet --cached HEAD breaks if there's a file called HEAD in the repo; you need to use git diff-index --no-ext-diff --quiet --cached HEAD --, see here.

Finally, I found plumbing commands to be slower than the porcelain commands when the goal is to ignore untracked files in a repo with many large untracked files (not WebKit in this case) with git 2.29.2:

  • time (git diff-files --quiet --no-ext-diff || (git update-index -q --refresh; git diff-index --quiet --no-ext-diff --cached HEAD --))
    • 255 ms mean
  • time git status --porcelain --untracked-files=no > /dev/null
    • 110 ms mean

This was also observed here.

Do there exist any plumbing commands that are as fast and as correct as the porcelain commands? (Also asked here.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment