The short format output of the git status command1 gives an output that can be used in a programmatic way:
In the short-format, the status of each path is shown as one of these forms
XY PATH
XY ORIG_PATH -> PATH
where ORIG_PATH is where the renamed/copied contents came from. ORIG_PATH is only shown when the entry is renamed or copied. The XY is a two-letter status code.
Further down, an older (more-quotable) version of the documentation2 says:
For paths with merge conflicts, X and Y show the modification states of each side of the merge. For paths that do not have merge conflicts, X shows the status of the index, and Y shows the status of the work tree. For untracked paths, XY are ??. Other status codes can be interpreted as follows:
- ' ' = unmodified
- M = modified
- T = file type changed (regular file, symbolic link or submodule)2
- A = added
- D = deleted
- R = renamed
- C = copied (if config option status.renamesis set to "copies")2
- U = updated but unmerged
Ignored files are not listed, unless --ignored option is in effect, in which case XY are !!.
The short format is obtained by using git status -s. This should give you all entries that have been staged so far:
git status -s | grep "^[MTADRCU]"
You can also add the -c flag to grep to count the lines instead of printing them.
Bonus: Anything new to the working tree that hasn't been staged yet (is still untracked) can be found with:
git status -s | grep "^??"
1 This text is also available as the helppage at git status --help.
2 The up-to-date documentation version is less succinct, owing to more explicit language around merge conflicts. I have marked codes that were added or modified in a Git version after the quoted version.