1180

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.

0

18 Answers 18

1620

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)

Sign up to request clarification or add additional context in comments.

12 Comments

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.
@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.
git diff --shortstat <commit1> <commit2> was the one I wanted.
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
@Bryson Yes, that's why that line says <commit-ish> - it works with anything that represents a commit, including literal commits, branches, tags, and refs in general. See also stackoverflow.com/questions/23303549/…
|
433
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 

6 Comments

Cool! but.. be aware that this only works with unstaged changes
If you've staged changes with git add, make sure to do git diff --shortstat --cached
@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(-).
shortstats doesn't show the number of lines, but the number of characters!
@JHBonarius According to the docs, --shortstat shows lines, not characters: git-scm.com/docs/git-diff#Documentation/…
|
276
+500

For the lazy, use git log --stat.

2 Comments

I found this useful, added a -10 to show the previous ten commits.
When you are finished viewing commit history, type Q to return to the terminal.
63
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.

5 Comments

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.)
The output of this is nothing for me.
@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.
or if uncommited git diff --stat HEAD
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.
50

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.

Comments

29

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.

3 Comments

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 "<commit1>..<commit2>".
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(-)\"}' #"
If you name the script git-summary and it's in your path, you can call it as git summary without the alias.
22

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(-)

Comments

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(-) 

7 Comments

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).
This happened to me too. The two commits were in the wrong order, swapping them around fixed it.
Updated the commit order and clarified what the two SHAs represent. Thanks for catching it :)
The --shortstat flag is awesome, it works with git diff though (not git log).
How to summarize them?
|
20

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 

Comments

11
git log --numstat 

just gives you only the numbers

Comments

11

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

git diff --shortstat HEAD 

Comments

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 

Comments

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 Comment

This gives "'tail' is not recognized as an internal or external command, operable program or batch file."
3

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

Comments

2

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.

Comments

2

This command will compare local files with remote files

git diff --stat 

Comments

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)}' 

Example:

using commit id's:

git log c9344e0be05b8038c244a4e9a531a199b961699c..947d05662b3b418cfaaa576d1e9585912a4e52dc --numstat --pretty="%H" --author="Krishna Chaitanya Surapaneni" | 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)}' 

output:-

total lines added: +91 total lines deleted: -3 total commits: 7 

using branches:

git log main..v3.2.0 --numstat --pretty="%H" --author="Krishna Chaitanya Surapaneni" | 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)}' 

output:-

total lines added: +23 total lines deleted: -3 total commits: 2 

This repo -> https://github.com/kcsurapaneni/food-delivery-backend/tree/main has been used for the example.

1 Comment

@4n70wa be more specific. It's working for me, may be you missed to replace the <author-name>. You can always share an example by taking any of the open source project, so that I can cross check your claim.
0

If you just want totals between two points (commits, tags, or branches):

git diff --shortstat <from> <to> 

To count the number of lines since the branch was created:

git diff --shortstat origin/HEAD... 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.