163

"git diff --stat" and "git log --stat" show output like:

$ git diff -C --stat HEAD c9af3e6136e8aec1f79368c2a6164e56bf7a7e07
 app/controllers/application_controller.rb |   34 +++-------------------------
 1 files changed, 4 insertions(+), 30 deletions(-)

But what really happened in that commit was that 4 lines were changed and 26 lines were deleted which is different than adding 4 lines and deleting 30.

Is there any way of getting the delta LOCs (26 in this case)? I don't really care about differentiating between lines added or removed.

Juan Alonso
  • 1,824
  • 2
  • 11
  • 14

5 Answers5

170

You can use:

git diff --numstat

to get numerical diff information.

As far as separating modification from an add and remove pair, --word-diff might help. You could try something like this:

MOD_PATTERN='^.+(\[-|\{\+).*$' \
ADD_PATTERN='^\{\+.*\+\}$' \
REM_PATTERN='^\[-.*-\]$' \
git diff --word-diff --unified=0 | sed -nr \
    -e "s/$MOD_PATTERN/modified/p" \
    -e "s/$ADD_PATTERN/added/p" \
    -e "s/$REM_PATTERN/removed/p" \
    | sort | uniq -c

It's a little long-winded so you may want to parse it in your own script instead.

Iulian Onofrei
  • 8,409
  • 9
  • 67
  • 106
quornian
  • 8,558
  • 5
  • 25
  • 26
  • 2
    Thanks quornian but numstat gives exactly the same info as stat, additions and deletions. – Juan Alonso Mar 30 '12 at 14:19
  • Updated my answer to include an example use of `--word-diff`. That might be more useful. – quornian Apr 01 '12 at 19:53
  • Thanks! Your edited answer is great. I wanted to see how many lines were added/modified/removed between two specific commits. To others who may wish to do the same, just put the branch names in the command, as in: `git diff commit1 commit2 --word-diff ...` where commit1/2 are SHA1s, branches, tags, etc... – Drew Noakes Nov 24 '13 at 19:04
  • 19
    The output of `git diff --numstat` is broken down by file. To see the total added/removed for the diff, you can pipe it to awk: `git diff --numstat | awk '{ added += $1; removed += $2 } END { print "+" added " -" removed }'` – hughes Dec 01 '15 at 02:49
  • 44
    @hughes A simpler way of obtaining the same information would be `git diff --shortstat`. In my experience it is equivalent to accumulating the output of `git diff --numstat`. – klaus triendl Sep 09 '18 at 12:30
  • 3
    Also FWIW to see the stats for staged changes, simply add `--cached` – xlm Nov 07 '18 at 06:56
  • In case anyone else is wondering about the output from `--numstat`, the two numbers are lines added and lines removed in that order, so `1 10 test/some_test.rb` means 1 added and 10 removed. – Sam Mar 08 '22 at 12:04
98
  1. If you want to know the lines added/changed/deleted by a commit with id commit-id, you could use

    git show commit-id --stat
    

    or

    git diff commit-id-before commit-id --stat
    
  2. If you wat to know the lines added/changed/deleted by a range commits, you could use

    git diff commit-id1 commit-id2 --stat
    
  3. If you want to know the lines added/changed/deleted by each commit, you could use

    git log --stat
    
wjandrea
  • 23,210
  • 7
  • 49
  • 68
yhluo
  • 1,129
  • 7
  • 5
  • 1
    That solution doesn't answer the question, "git --stat" counts a single modified line as "1 insertion and 1 deletion". The question asks how to get "1 changed". – Juan Alonso May 01 '20 at 10:31
21

You could use diffstat to show the number of modified lines. For example:

git diff HEAD c9af3e6136e8 | diffstat -Cm

The -C option is for getting colorized output; the -m option is for showing the number of modified lines. Sample output:

 app/controllers/application_controller.rb |   30 -------------------!!!
 1 files changed, 0 insertions(+), 26 deletions(-), 4 modifications(!)

Note that the number of lines in each category (insertions, deletions, modifications) is only approximate, as man diffstat says:

-m merge insert/delete counts from each "chunk" of the patch file to approximate a count of the modified lines.

diffstat has a missing feature when compared to git diff --stat: diffstat is incapable of showing file moves/renames (e.g. app/{a.rb => b.rb}), unlike git diff --stat which is capable of showing this information by using the -M (--find-renames) option or by setting diff.renames in the git configuration file (refer to man git-config).

Flux
  • 7,901
  • 5
  • 33
  • 76
13

If all of your files are staged for commit, to see the --numstat go like this:

git diff --numstat --cached

example output

32      32      project.pbxproj

--numstat [...] shows number of added and deleted lines

Gianfranco P.
  • 8,605
  • 5
  • 46
  • 64
Falieson
  • 1,880
  • 3
  • 22
  • 34
4

git uses "unified" diff, which only has added and deleted lines, as the diff format. You have to do something external to get a diff that shows add, delete, and change information.

https://wiki.postgresql.org/wiki/Working_with_Git#Context_diffs_with_Git gives links to a script that allows running regular old "diff" - and from that you can generate a "context" diff output. Context diff does show added, removed, and changed lines, which should allow you to get the data you want.

Daniel Pittman
  • 16,227
  • 4
  • 39
  • 34
  • Voted down for linking to an article instead of reproducing the relevant information here. The article no longer contains the relevant section. (Admittedly, it happens to be a wiki with available edit history, but Stack Overflow answers should stand on their own regardless.) – Amir Dec 28 '21 at 14:04
  • For anyone who wants to easily get to the content that was removed in an edit, here a link to the old page: https://wiki.postgresql.org/index.php?title=Working_with_Git&oldid=31690#Context_diffs_with_Git – Michael Burr Jan 14 '22 at 22:23