1089

Is there any easy way to calculate the number of lines changed between two commits in Git?

I know I can do a git diff, and count the lines, but this seems tedious. I'd also like to know how I can do this, including only my own commits in the line counts.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Mike
  • 23,892
  • 18
  • 70
  • 90

17 Answers17

1518

You want the --stat option of git diff, or if you're looking to parse this in a script, the --numstat option.

git diff --stat <commit-ish> <commit-ish>

--stat produces the human-readable output you're used to seeing after merges; --numstat produces a nice table layout that scripts can easily interpret.

I somehow missed that you were looking to do this on multiple commits at the same time - that's a task for git log. Ron DeVera touches on this, but you can actually do a lot more than what he mentions. Since git log internally calls the diff machinery in order to print requested information, you can give it any of the diff stat options - not just --shortstat. What you likely want to use is:

git log --author="Your name" --stat <commit1>..<commit2>

but you can use --numstat or --shortstat as well. git log can also select commits in a variety other ways - have a look at the documentation. You might be interested in things like --since (rather than specifying commit ranges, just select commits since last week) and --no-merges (merge commits don't actually introduce changes), as well as the pretty output options (--pretty=oneline, short, medium, full...).

Here's a one-liner to get total changes instead of per-commit changes from git log (change the commit selection options as desired - this is commits by you, from commit1 to commit2):

git log --numstat --pretty="%H" --author="Your Name" commit1..commit2 | awk 'NF==3 {plus+=$1; minus+=$2} END {printf("+%d, -%d\n", plus, minus)}'

(you have to let git log print some identifying information about the commit; I arbitrarily chose the hash, then used awk to only pick out the lines with three fields, which are the ones with the stat information)

Community
  • 1
  • 1
Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • 7
    This does not answer to the original question about "changed lines". One line change is calculated as both inserted and deleted line. Calculating number of changed lines needs more work than described here. – Ville Laitila Jan 26 '12 at 09:52
  • 17
    @VilleLaitila: This is as close as you can get without an absurd amount of effort, and it was good enough for the OP and 15 others. (How do you define when a changed line becomes an added line and a deleted line? By edit distance between the - and + line, as a fraction of line length?) We all know that changes get doubled; we can just call that a useful metric of amount of change, and move on with our lives. – Cascabel Jan 26 '12 at 14:23
  • 303
    `git diff --shortstat ` was the one I wanted. – Kim Oct 24 '12 at 09:20
  • 14
    For reference, the date format for `--since` and `--until` is something like: `yesterday`, `1 month 2 weeks 3 days 1 hour 1 second ago`, or `1979-02-26 18:30:00` – juanmirocks Apr 01 '13 at 08:01
  • Does these numbers include lines deleted as a result of deleting a file? – Karl Apr 25 '14 at 12:00
  • You can filter the file types by inserting `-- *.m *.h *.java` before the `| awk` part. I found this handy for only counting actual code file changes. – Ben Clayton Oct 16 '14 at 09:02
  • 1
    @Karl: Yes it does. If a file was deleted with 300 lines, then it will show 300 lines removed. – hazrpg Sep 03 '15 at 08:32
  • @Jefromi what is the difference between git diff --stat and git log --stat ? I get that the first one is giving the difference between the range of the 2 commits, but what the other does? – Kasun Siyambalapitiya Nov 25 '16 at 11:52
  • 5
    @Bryson Yes, that's why that line says `` - it works with anything that *represents* a commit, including literal commits, branches, tags, and refs in general. See also http://stackoverflow.com/questions/23303549/what-are-commit-ish-and-tree-ish-in-git – Cascabel Mar 03 '17 at 21:35
  • 1
    Get number of lines for changed and not committed files: `git diff --stat` – Finesse Dec 11 '17 at 05:57
  • 2
    `git diff --shortstat HEAD~1 HEAD` did what I needed, thank you @Kim – EpicPandaForce Feb 03 '20 at 17:37
365
git diff --shortstat

gives you just the number of lines changed and added. This only works with unstaged changes. To compare against a branch:

git diff --shortstat some-branch
Brad
  • 159,648
  • 54
  • 349
  • 530
orkoden
  • 18,946
  • 4
  • 59
  • 50
  • 6
    Cool! but.. be aware that this only works with unstaged changes – TomCobo Nov 16 '18 at 12:02
  • 20
    If you've staged changes with `git add`, make sure to do `git diff --shortstat --cached` – TomNash Jul 31 '19 at 20:12
  • 2463 files changed, 39745 insertions(+), 21383 deletions(-) I've actually deleted around 5k to 10k in the last month. It's nearly all I've been doing apart from moving things around. Something is wrong. It doesn't include removed files or something? – jgmjgm Aug 08 '19 at 19:56
  • 2
    @jgmjgm, try using `git merge-base` as part of your command. You probably just have a newer `master` branch than what your `feature_branch` was originally based on, is all, so you need to do `git diff` against the old base upon which your feature branch was based. That can be found with `git merge-base`, like this: sample command: `git diff --shortstat $(git merge-base HEAD master) HEAD`. Sample output: `13 files changed, 955 insertions(+), 3 deletions(-)`. Good. That's correct. This: `git diff --shortstat master`, however, shows: `1643 files changed, 114890 insertions(+), 16943 deletions(-)`. – Gabriel Staples Aug 24 '20 at 23:36
  • 2
    shortstats doesn't show the number of _lines_, but the number of _characters_! – JHBonarius Feb 21 '21 at 09:39
  • 3
    @JHBonarius According to the docs, --shortstat shows lines, not characters: https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---shortstat – Zachary Ryan Smith Apr 15 '22 at 13:47
249

For the lazy, use git log --stat.

Thomas
  • 8,306
  • 8
  • 53
  • 92
59
git diff --stat commit1 commit2

EDIT: You have to specify the commits as well (without parameters it compares the working directory against the index). E.g.

git diff --stat HEAD^ HEAD

to compare the parent of HEAD with HEAD.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 1
    There's never really any need to use `diff-index` - the `diff` frontend can handle everything; the case of `diff-index` is covered by the `--cached/--staged`, I believe. (And there's no way to use `diff-index` to compare two arbitrary commits as the OP asked.) – Cascabel Mar 27 '10 at 04:17
  • The output of this is nothing for me. – Mike Mar 27 '10 at 04:47
  • @Mike: Did you leave off a carat? Was your most recent commit a merge commit? If git says there's no diff, it's because there's no diff. – Cascabel Mar 27 '10 at 06:46
  • 10
    or if uncommited `git diff --stat HEAD` – wieczorek1990 Mar 23 '16 at 16:47
  • 1
    Also, you can compare further back than just the parent by using `HEAD~n`, where `n` is how far you want to go back. `git diff --stat HEAD~5 HEAD` will show combined stats for the last 5 commits relative to HEAD. – Nathan Beck Jul 09 '19 at 20:48
38

Short statistics about the last commit :

git diff --shortstat HEAD~1 HEAD

In my case, this gives me the following information:

 254 files changed, 37 insertions(+), 10773 deletions(-)

Insertions and deletions are affected lines.

Spyryto
  • 1,107
  • 12
  • 17
25

I just solved this problem for myself, so I'll share what I came up with. Here's the end result:

> git summary --since=yesterday
total: 114 file changes, 13800 insertions(+) 638 deletions(-)

The underlying command looks like this:

git log --numstat --format="" "$@" | awk '{files += 1}{ins += $1}{del += $2} END{print "total: "files" files, "ins" insertions(+) "del" deletions(-)"}'

Note the $@ in the log command to pass on your arguments such as --author="Brian" or --since=yesterday.

Escaping the awk to put it into a git alias was messy, so instead, I put it into an executable script on my path (~/bin/git-stat-sum), then used the script in the alias in my .gitconfig:

[alias]
    summary = !git-stat-sum \"$@\"

And it works really well. One last thing to note is that file changes is the number of changes to files, not the number of unique files changed. That's what I was looking for, but it may not be what you expect.

Here's another example or two

git summary --author=brian
git summary master..dev
# combine them as you like
git summary --author=brian master..dev
git summary --all

Really, you should be able to replace any git log command with git summary.

undefined
  • 6,208
  • 3
  • 49
  • 59
  • 2
    It should be the accepted answer as it is the only one that actually answer it : make a sum to show the total lines changed. Other responses show total for each line or each commit but do not summarize them. You should just improve it by replacing "$@" with "..". – bN_ Nov 03 '20 at 09:26
  • 1
    Here is the command escaped for use in a git alias `summary = "!git log --numstat --format=\"\" \"$@\" | awk '{files += 1}{ins += $1}{del += $2} END{print \"total: \"files\" files, \"ins\" insertions(+) \"del\" deletions(-)\"}' #"` – user1626227 Apr 06 '21 at 09:11
  • 2
    If you name the script `git-summary` and it's in your path, you can [call it as `git summary` without the alias](https://www.atlassian.com/git/articles/extending-git). – idbrii Oct 06 '21 at 17:01
20

Assuming that you want to compare all of your commits between abcd123 (the first commit) and wxyz789 (the last commit), inclusive:

git log wxyz789^..abcd123 --oneline --shortstat --author="Mike Surname"

This gives succinct output like:

abcd123 Made things better
 3 files changed, 14 insertions(+), 159 deletions(-)
wxyz789 Made things more betterer
 26 files changed, 53 insertions(+), 58 deletions(-)
Ron DeVera
  • 14,394
  • 6
  • 41
  • 36
  • 1
    The output of this is nothing for me (I've made commits and verified --author is correct by using it with git log and no other arguments). – Mike Mar 27 '10 at 04:46
  • This happened to me too. The two commits were in the wrong order, swapping them around fixed it. – bob esponja Jan 08 '13 at 01:04
  • 1
    Updated the commit order and clarified what the two SHAs represent. Thanks for catching it :) – Ron DeVera Mar 05 '14 at 06:01
  • 3
    The `--shortstat` flag is awesome, it works with `git diff` though (not `git log`). – lucke84 May 13 '15 at 15:38
  • How to summarize them? – Idemax Jan 31 '17 at 09:30
  • Is there way to get a total for all commits? – Douglas Gaskell Aug 11 '18 at 01:50
  • The first commit in the command must be the oldest one, and the second one must be the newest commit in order for the command to show the correct output. I've also just used `git log HEAD~10..HEAD --oneline --shortstat --author="Mike Surname"` and got the correct output, and it seems a little simpler to use, it will scan the last 10 commits in this case and output the summary for the commits where the author is the one you mention. – GreatDane Sep 03 '21 at 08:15
19

Another way to get all change log in a specified period of time

git log --author="Tri Nguyen" --oneline --shortstat --before="2017-03-20" --after="2017-03-10"

Output:

2637cc736 Revert changed code
 1 file changed, 5 insertions(+), 5 deletions(-)
ba8d29402 Fix review
 2 files changed, 4 insertions(+), 11 deletions(-)

With a long output content, you can export to file for more readable

git log --author="Tri Nguyen" --oneline --shortstat --before="2017-03-20" --after="2017-03-10" > /mnt/MyChangeLog.txt
gvlasov
  • 18,638
  • 21
  • 74
  • 110
nmtri
  • 444
  • 3
  • 6
15

Good one to summarize the year

git diff --shortstat <first commit number of the year> HEAD

get results 270 files changed, 19175 insertions(+), 1979 deletions(-)

nassy
  • 201
  • 3
  • 5
11
git log --numstat 

just gives you only the numbers

Maifee Ul Asad
  • 3,992
  • 6
  • 38
  • 86
nibinbhaskar
  • 177
  • 1
  • 4
5

If you want to see the changes including the # of lines that changed between your branch and another branch,

git diff the_other_branch_name --stat
sinsadmim
  • 51
  • 1
  • 1
3

Though all above answers are correct, below one is handy to use if you need count of last many commits

below one is to get count of last 5 commits

git diff $(git log -5 --pretty=format:"%h" | tail -1) --shortstat

to get count of last 10 commits

git diff $(git log -10 --pretty=format:"%h" | tail -1) --shortstat

generic - change N with count of last many commits you need

git diff $(git log -N --pretty=format:"%h" | tail -1) --shortstat

to get count of all commits since start

git diff $(git log --pretty=format:"%h" | tail -1) --shortstat

1

I wanted to have the insertions and deletions go into the sum, in case someone else needs the same here goes:

# get the log      filter useless parts      calculate the sum    and print it
git log --numstat | grep -vE '^[^0-9]' | awk '{sum += $1 + $2} END {print sum}'

This is not as versatile as some of the other solutions (for example the one undefined posted), but gives just a bare number, which was nice for my use case

Fynn
  • 303
  • 1
  • 11
0

git diff --stat will double-count modified lines. If this is a problem for you, you can do this instead:

git diff | diffstat -Cm

This will give you the same output, except that it will [try to] differentiate between added+deleted lines and modified lines.

forresthopkinsa
  • 1,339
  • 1
  • 24
  • 29
0

This command will compare local files with remote files

git diff --stat
-1

If you want to check the number of insertions, deletions & commits, between two branches or commits.

using commit id's:

git log <commit-id>..<commit-id> --numstat --pretty="%H" --author="<author-name>" | awk 'NF==3 {added+=$1; deleted+=$2} NF==1 {commit++} END {printf("total lines added: +%d\ntotal lines deleted: -%d\ntotal commits: %d\n", added, deleted, commit)}'

using branches:

git log <parent-branch>..<child-branch> --numstat --pretty="%H" --author="<author-name>" | awk 'NF==3 {added+=$1; deleted+=$2} NF==1 {commit++} END {printf("total lines added: +%d\ntotal lines deleted: -%d\ntotal commits: %d\n", added, deleted, commit)}'
KCS
  • 442
  • 5
  • 20
  • don't work. shows only zero: ```total lines added: +0 total lines deleted: -0 total commits: 0``` – 4n70wa Jul 26 '22 at 19:16
-1

to get quickly how many files have been changed and lines added, just run.

git diff --shortstat HEAD
codemania23
  • 913
  • 11
  • 19