Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number of modified files in git index

Tags:

git

How can I find out the number of modified files in the index? That is to say, files that show as "modified" when running git status.

I know lots of visual git tools that do this, as well as shell add-ons that show the count next to the prompt, but I just don't see how to do it on the command line in a reasonable way.

like image 744
Rikki Gibson Avatar asked Nov 06 '17 21:11

Rikki Gibson


2 Answers

You can get the number of modified file using :

git status -s -uno | wc -l

From the git status documentation, -s give output in short format, and -uno does not show untrack files.

like image 190
mpromonet Avatar answered Sep 18 '22 20:09

mpromonet


TL;DR

You probably want either HEAD vs work-tree or HEAD vs index, or perhaps HEAD vs index plus index vs work-tree. If you want to keep the two comparisons separate, you cannot do it in one step.

Long description

There are several possible answers depending on precisely what question you meant. Note that for all of the diff commands below, you can use --name-only if you're not interested in the particular change(s) in the file(s). The status letter (Added, Deleted, Modified, etc.) is useful if you decide to add --diff-filter to choose to examine only specific kinds of changes. For instance, if you want to know how many files are strictly modified, not counting files added or deleted, you could filter on M.

  1. git diff --cached --name-status HEAD | wc -l
  2. git diff --name-status HEAD | wc -l
  3. git diff --name-status | wc -l
  4. git status -s -uno | wc -l (as in mpromonet's comment).

Each produces a different result:

  1. Compares HEAD to the index: what would be different in the commit you would make now if you ran git commit right now, compared to what's in the commit that is HEAD right now? That is, you have a current commit now, and if you make a new commit, the current commit will be the new commit's parent. What will be different?

    (Remember, the index represents the next commit to make. It starts out with copies of the exact same files as in HEAD. Each time you git add a file, you copy the file back from the work-tree, into the index. This is therefore comparing what you will commit now if you commit, to what you have in your HEAD commit. As a special case here, you can omit the name HEAD; --cached will assume HEAD.)

    In the long git status output, these come out in the first section: Changes to be committed.

  2. Compares HEAD to the work-tree. These are files that are modified in the work-tree, but are not staged for commit. In the longer git status output, these generally come out in the second section, Changes not staged for commit—but see the very next bit.

  3. Compares the index to the work-tree. These, too, are files that are modified in the work-tree—but this time they're changed with respect to the files already copied back into the index. To the extent that the index matches the HEAD commit, #2 and #3 produce the same list of files. But suppose README is in HEAD as Version H (for Head). You modify README and git add README, copying version W (for Work-tree) into version I (for Index). Then you modify version W again. Now all three are different! Using git status --short or git status -s, you will see MM README in the output: it's modified twice.

    The output from this section is really what shows up in the second half of the git status output, the Changes not staged for commit part.

  4. Compares HEAD vs index, then compares index vs work-tree, then prints—in a summary, combined format—the name and status of each file, using two letters for each file.

To illustrate this clearly, consider this repository with a single initial commit, with one file in it. The file is named README and the initial commit version contains the text Read me.

$ git init
Initialized empty Git repository in ...
$ echo 'Read me.' > README
$ git add README
$ git commit -m initial
[master (root-commit) a9362c4] initial
 1 file changed, 1 insertion(+)
 create mode 100644 README
$ echo 'Please read me.' > README
$ git add README
$ echo 'Read me, for I am very readable.' > README

There are now three active versions of file README, and:

$ git status -s
MM README

The long version of git status shows us that README is both ready to commit, and has changes not staged for commit:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   README

Look, though, at what happens if we put the initial text back, then compare HEAD to the work-tree:

$ echo 'Read me.' > README
$ git diff --name-status HEAD
$

The current commit matches the work-tree, so there is no difference here. If you git add README, the short status goes from MM README to empty:

$ git status -s
MM README
$ git add README
$ git status -s
$

So, if you are wondering "what do I get if I add and commit everything", you will want to compare HEAD with the work-tree. If you are wondering "what do I get if I commit now", you want to compare HEAD to index.

like image 22
torek Avatar answered Sep 20 '22 20:09

torek