Git diff with line numbers (Git log with line numbers)

Solution 1:

You can't get human-readable line numbers with git diff

There aren't currently any options to get line-numbers displayed vertically on the side with git diff.

Unified-diff format

That information is available in the (c)hunk headers for each change in the diff though, it's just in unified-diff format:

@@ -start,count +start,count @@

The original state of the file is represented with -, and the new state is represented with + (they don't mean additions and deletions in the hunk header. start represents the starting line number of each version of the file, and count represents how many lines are included, starting from the start point.

Example

diff --git a/osx/.gitconfig b/osx/.gitconfig
index 4fd8f04..fcd220c 100644
--- a/osx/.gitconfig
+++ b/osx/.gitconfig
@@ -11,7 +11,7 @@ <== HERE!
 [color "branch"]
        upstream = cyan
 [color "diff"]
-       meta = yellow
+       meta = cyan
        plain = white dim
        old = red bold
        new = green bold

The hunk header

@@ -11,7 +11,7 @@

says that the previous version of the file starts at line 11, and includes 7 lines:

11  [color "branch"]
12         upstream = cyan
13  [color "diff"]
14 -       meta = yellow
14 +       meta = cyan
15         plain = white dim
16         old = red bold
17         new = green bold

while the next version of the file also starts at line 11, and also includes 7 lines.

Unified-diff format isn't really for human consumption

As you can probably tell, unified-diff format doesn't make it easy to figure out line numbers (at least if you're not a machine). If you really want line numbers that you can read, you'll need to use a diffing tool that will display them for you.

Additional Reading

  • Official git-diff(1) Manual Page

Solution 2:

Here's another solution, expanding on Andy Talkowski's code.

Plain text:

git diff | gawk '
  match($0,"^@@ -([0-9]+),([0-9]+) [+]([0-9]+),([0-9]+) @@",a){
    left=a[1]
    ll=length(a[2])
    right=a[3]
    rl=length(a[4])
  }
  /^(---|\+\+\+|[^-+ ])/{ print;next }
  { line=substr($0,2) }
  /^[-]/{ printf "-%"ll"s %"rl"s:%s\n",left++,""     ,line;next }
  /^[+]/{ printf "+%"ll"s %"rl"s:%s\n",""    ,right++,line;next }
        { printf " %"ll"s %"rl"s:%s\n",left++,right++,line }
'

Here's sample output:

diff --git a/.bashrc b/.bashrc
index b2b6d5f..51e0b8c 100644
--- a/.bashrc
+++ b/.bashrc
@@ -1,8 +1,26 @@
 1  1:#!/bin/bash
-2   :# ~/.bashrc: executed by bash(1) for non-login shells.
-3   :# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
-4   :# for examples
+   2:# 2020-03-06 14:54:25 From R S:
+   3:##export PATH="/usr/local/opt/ed/libexec/gnubin:$PATH"
+   4:#export PATH="/usr/local/opt/findutils/libexec/gnubin:$PATH"
+   5:#export PATH="/usr/local/opt/gnu-indent/libexec/gnubin:$PATH"
+   6:#export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"
+   7:#export PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
+   8:#export PATH="/usr/local/opt/gnu-which/libexec/gnubin:$PATH"
 5  9:
+  10:export PATH="/usr/local/opt/sqlite/bin:$PATH"
+  11:export PATH="/usr/local/opt/file-formula/bin:$PATH"
+  12:export PATH="/usr/local/opt/unzip/bin:$PATH"
+  13:export PATH="/usr/local/opt/openssl/bin:$PATH"
+  14:export PATH="/usr/local/opt/wireshark/bin:$PATH"
+  15:
+  16:
+  17:#export PATH="/usr/local/opt/grep/libexec/gnubin:$PATH"