20

I would like to see the status of the current directory. Because there are lots of changes in sub-directories, which I do not want to see, the following command doesn't do the trick:

git status .

Is there any way of getting this kind of report, short of grepping the output of git status?

jub0bs
  • 60,866
  • 25
  • 183
  • 186
blueFast
  • 41,341
  • 63
  • 198
  • 344

4 Answers4

11

Use git-status -- <pathspec>...

The synopsis of the git-status man page tells you that you can filter by paths:

git status [<options>...] [--] [<pathspec>...]

Therefore, all you have to do is get a list of paths corresponding to the regular (non-directory) files in the current directory, and pass that to git-status.

There is one gotcha: because git status reports about the whole repository if passed an empty <pathspec>... argument, you need to check whether the list is empty or not.

Shell script

Here is a small shell script that does what you want.

#!/bin/sh

# git-status-dot
#
# Show the status of non-directory files (if any) in the working directory
#
# To make a Git alias called 'status-dot' out of this script,
# put the latter on your search path, make it executable, and run
#
#   git config --global alias.status-dot '! git-status-dot'

# Because GIt aliases are run from the top-level directory of the repo,
# we need to change directory back to $GIT_PREFIX.
[ "$GIT_PREFIX" != "" ] && cd "$GIT_PREFIX"

# List Non-Directory Files in the Current Directory
lsnondirdot=$(ls -ap | grep -v /)

# If "lsnondirdot" is not empty, pass its value to "git status".
if [ -n "$lsnondirdot" ]
then
    git status -- $lsnondirdot
else
    printf "No non-directory files in the working directory\n"
fi

exit $?

For more details about why the GIT_PREFIX shenanigans are required, see git aliases operate in the wrong directory.

The script is available at Jubobs/git-aliases on GitHub.

Make a Git alias out of it

For convenience, you can create a Git alias that calls the script; make sure the script is on your path, though.

git config --global alias.statusdot '!sh git-status-dot.sh'

Toy example

Here is a toy example demonstrating how to use the resulting alias and what it does.

# initialize a repo
$ mkdir testgit
$ cd testgit
$ git init

# create two files
$ mkdir foo
$ touch foo/foo.txt
$ touch bar.txt

# good old git status reports that subdir/test1.txt is untracked... 
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    bar.txt
    foo/

nothing added to commit but untracked files present (use "git add" to track)
# ... whereas our new alias, git status-dot, only cares
# about regular files in the current directory
$ git status-dot
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    bar.txt

nothing added to commit but untracked files present (use "git add" to track)

# and if we delete README.md ...
$ rm README.md
# ... good old git status still bother us about /subdir ...
$ git status
Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    foo/

nothing added to commit but untracked files present (use "git add" to track)
# ... whereas git statusdot doesn't
$ git status-dot
No non-directory files in the working directory
$
Community
  • 1
  • 1
jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • 1
    I would suggest adding a message if `lsrfdot` is empty; something like `No files in the current directory`. Furthermore it might make sense to use `ls -ap` to include unix style hidden files. – Sascha Wolf Mar 18 '15 at 15:28
  • 1
    Nicely done! +1. Zeeker's suggestions seem sensible too. – VonC Mar 18 '15 at 15:29
  • @Zeeker Excellent suggestion. I'll do that. – jub0bs Mar 18 '15 at 15:36
  • 1
    Small typo in the script (lsrdot), otherwise good solution. A pity that git does not provide this out of the box (seems like a useful feature to me) – blueFast Mar 18 '15 at 15:59
  • 1
    Nice solution. It comprises the ideas, arguments and suggestions that emerged in this page in the other answers and their comments. +1 from me too. – axiac Mar 18 '15 at 16:37
5

Maybe there's a more proper way to do this, but you can simply

find . -maxdepth 1 -type f -print0 | xargs -0 git status

Of course, this fails if there's no regular files on the current directory. In that case, you can use the extra ugly version

find . -maxdepth 1 -type f -print0 | xargs -0 git status nonexistentfile

And, no, I'm not going to address the case where you have a file named nonexistentfile.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
loopbackbee
  • 21,962
  • 10
  • 62
  • 97
  • I get `find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.` from this. – Holloway Mar 18 '15 at 14:21
  • @Trengot you can safely ignore it. I've edited the answer to avoid the warning – loopbackbee Mar 18 '15 at 14:23
  • 1
    I'm not sure this is what OP was after. If I do this I get changes in subdirectories. – Holloway Mar 18 '15 at 14:28
  • Should use `find -print0` and `xargs -0` to avoid escaping issues with some file names. – Andrew Marshall Mar 18 '15 at 14:30
  • @AndrewMarshall you're absolutely right, I've added them to the answer – loopbackbee Mar 18 '15 at 14:36
  • @Trengot do those subdirectories appear on `find . -maxdepth 1 -type f`? – loopbackbee Mar 18 '15 at 14:38
  • @goncalopp no. Nothing is returned (I have no files in the root of the repo). – Holloway Mar 18 '15 at 14:39
  • @Trengot that's the problem then. I've added a "fix". This is getting uglier by the minute – loopbackbee Mar 18 '15 at 14:47
  • Usually I don't add this kind of comments but +1 for "And, no, I'm not going to address the case where you have a file named `nonexistentfile`". That made me laught. Good answer nonetherless. – Sascha Wolf Mar 18 '15 at 14:58
4

You can use:

git status | grep -v /

to filter out any paths that contain a slash (/) which means they are in subdirectories.

You will also lose the red/green coloring of the changed paths.

Update:

This solution does not display the files that are moved from or to the current directory because the source and destination of a move operation are displayed on the same line in the output. The files that were renamed in the current directory (without being moved between directories) are displayed though.

axiac
  • 68,258
  • 9
  • 99
  • 134
  • That's not the right way to do it. If you don't have any changes in the current directory but you do further down in the file-system hierarchy, the output of `git status` will contain stuff relevant to those changes. You need to filter stuff out *before* calling `git status`. – jub0bs Mar 18 '15 at 14:42
  • @Jubobs, OP wants to ignore changes further down the hierarchy. – Holloway Mar 18 '15 at 14:43
  • @Trengot I know; that's my point: this command will contain output relevant to changes further down the hierarchy. Grepping the output of an unfiltered `git status` is not satisfactory. – jub0bs Mar 18 '15 at 14:48
  • 2
    Notice that the OP is explicitly excluding this solution in his question: `short of grepping the output of git status`. Although it's possibly the simplest... – loopbackbee Mar 18 '15 at 14:49
  • @Jubobs `git status` displays the paths of the new/modified/deleted files using relative paths. Everything that is not in the current directory will have at least one slash (`/`) in its relative path, no matter if it's in a subdirectory or in a parent directory (or a different subdirectory of a parent directory). `grep -v /` excludes all the lines that contain at least one `/`. The files in the current directory are not affected. Also the lines where `git` gives hints about what to do next are not affected. – axiac Mar 18 '15 at 14:49
  • @axiac You're missing my point... Unfortunately, I can't elaborate in a comment. – jub0bs Mar 18 '15 at 14:50
  • @goncalopp I did not notice that part of the request before. – axiac Mar 18 '15 at 14:54
  • @Jubobs the output of my command produces `git` comments and hints that apply to files that are excluded by `grep -v` and doesn't necessarily apply to the files in the current directory. But the list of files is correct. – axiac Mar 18 '15 at 14:59
  • @Jubobs do you mean the "Changes not staged for commit" type headings? You can get around this by using `git status -s` (or `git status --porcelain` to guarantee it won't change output in new git versions) – Holloway Mar 18 '15 at 15:00
  • On a second thought, `grep -v /` will ignore a file that was moved from or to the current directory as the source and destination of the move operation are listed on the same line. :-( – axiac Mar 18 '15 at 15:14
1

I believe the answer is no...

Unless the files are untracked files, submodules, or ignored files. The full documentation for the status command mentions nothing about limiting the output to the current directory.

However, you might want to consider using the stash command to clean up your working tree. If you stash everything not in your current directory (which requires the --patch option to only stash selective parts), then status will only show what you didn't stash. However, if you use stash multiple times while working, then you should always have a clean working tree and you could avoid this problem to begin with. Each body of work will be packaged up in a separate stash waiting until you are ready to commit it.

Of course, that doesn't help much with your current situation (aside from using (stash --patch). Another alternative you might want to try is the interactive mode of the add command. Then you can go through all the changed files and selectively add the ones you want (stash --patch works the same way).

Or, you can use the grep solutions suggested in other answers.

Waylan
  • 37,164
  • 12
  • 83
  • 109