Do Not Use git status --ignored


Sometimes it's useful to find all files in a git working copy that aren't being tracked in the repository. There's an --ignored switch for git status that's supposed to make it show the ignored files. Combined with --untracked-files, that should do the trick nicely. But the problem: The --ignored switch doesn't fucking work. Seriously.

To be more accurate, it only shows some of the ignored files (despite no mention of this fact in the man page). It's easy fooled: Just try adding someUntrackedDirWithUntrackedFiles/* to your .gitignore, and see if you can get git status to mention either the directory or the files inside it. Note that none of the settings for --untracked-files= fix this.

Wanna know the best part? There is no git command known to reliably do what --ignored claims to do. There are various alleged solutions floating around, but unfortunately they don't work. The author in that last link offers a suggestion, but still admits to a lack of confidence in it. Great.

My suggestion is what I recommend for git usage in general: Minimize your reliance on any features beyond the basics. For such an amazingly useful tool (I highly recommend switching to git if you're still on subversion - or worse, CVS or VSS), it's amazing how shitty git gets the deeper you dive into it.

In this case, I suggest using git ls-files to generate a list of the files that are under version control, stick them into a hash set (for quick lookup), then iterate over all the files in your working copy, outputting only the files that aren't in the hash set.

Here's how to do it in D:

/++ Show all unversioned (both untracked and ignored) files and directories in the current git working copy. Much like "git status --ignored --untracked-files=all" except this actually works (although you must run it from the root of the working copy). Further explanation: https://semitwist.com/articles/article/view/do-not-use-git-status-ignored Tested on DMD v2.063.2 Licensed under the WTFPL - Do What the Fuck You Want to Public License: http://www.wtfpl.net/ +/ import std.algorithm; import std.array; import std.file; import std.path; import std.process; import std.stdio; import std.string; string run(string cmd) { auto result = executeShell(cmd); if(result.status != 0) throw new Exception("Command failed: " ~ cmd); return result.output; } void main() { if(!exists(".git")) throw new Exception("Must run from the root of the git working copy"); bool[string] versionedFiles; auto gitOutput = run("git ls-files"); foreach(filename; gitOutput.splitter("\n")) { versionedFiles[filename] = true; // Also include the file's parent directories, since git likes to // pretend there's no such thing as directories: while(true) { auto parentDir = dirName(filename); if(parentDir == filename) break; // Done versionedFiles[parentDir] = true; filename = parentDir; } } foreach(DirEntry entry; dirEntries(".", SpanMode.breadth)) { // The output of "git ls-files" doesn't include the "./" prefix // (like DirEntry does) and uses forward slashes on all platforms. auto filename = entry.name.replace("\\", "/").chompPrefix("./"); if(filename !in versionedFiles) { if(entry.isDir) writeln(filename, "/"); else writeln(filename); } } }

1 comment for "Do Not Use git status --ignored"

  1. (Guest) Danny Arends
    2013-08-01 09:34

    Wow, nice trick !

Leave a comment

Captcha