When viewing a combined diff, if the two files you're comparing have a line that's different from what they were merged into, you will see the ++ to represent: one line that was added does not appear in either file1 or file2.
You can run the git diff HEAD command to compare the both staged and unstaged changes with your last commit. You can also run the git diff <branch_name1> <branch_name2> command to compare the changes from the first branch with changes from the second branch. Order does matter when you're comparing branches.
Comparing changes with git diffgit diff is a multi-use Git command that when executed runs a diff function on Git data sources. These data sources can be commits, branches, files and more.
git diff
There aren't currently any options to get line-numbers displayed vertically on the side with git diff
.
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.
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.
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.
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"
As of 24 May 2020, you can now use the third-party tool git diffn
(full disclosure: I wrote it) for this purpose. It's a light-weight wrapper around git diff
, written in the awk
pattern/action-based programming language. Here's a sample output from running git diffn
. The colons (:
) all staying white is intentional, to act as a visual queue that they are a separator from left to right. (If you don't like that, it's easy to change in the code).
From the top of git-diffn.sh
:
DESCRIPTION:
git-diffn.sh
a drop-in replacement for git diff
which also shows line 'n'umbers! Use it exactly like git diff
, except you'll see these beautiful line numbers as well to help you make sense of
your changes.
since it's just a light-weight awk-language-based wrapper around git diff
, it accepts ALL options and parameters that git diff
accepts. Examples:
git diffn HEAD~
git diffn HEAD~3..HEAD~2
works with any of your git diff
color settings, even if you are using custom colors
See my answer here for how to set custom diff colors, as well as to see a screenshot of custom-color output from git diffn
: How do you customize the color of the diff header in git diff?
Here are some sample git config
commands from my answer above to set custom git diff
colors and attributes (text formatting):
git config --global color.diff.meta "blue"
git config --global color.diff.old "black red strike"
git config --global color.diff.new "black green italic"
git config --global color.diff.context "yellow bold"
in git diffn
, color output is ON by default; if you want to disable the output color, you must use --no-color
or --color=never
. See man git diff
for details. Examples:
git diffn --color=never HEAD~
git diffn --no-color HEAD~3..HEAD~2
gawk
. If so, try this: brew install gawk
.Option 1 (my recommendation): download the whole repo and then create a symlink to the program so that you can easily receive updates by doing a git pull
from the repo whenever you want.
First, cd
to wherever you want to install this. Then run:
git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-diffn.sh" ~/bin/git-diffn
Done! Now just do the final step below!
Option 2 (for those who just want the 1 file): download just the one file one time.
mkdir -p ~/bin
cd ~/bin
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/git-diffn.sh
chmod +x git-diffn.sh
mv git-diffn.sh git-diffn
Done! Now just do the final step below!
Final step:
Now close and re-open your terminal, or re-source it with . ~/.bashrc
, and you are done!
git diffn
will now work as an exact drop-in replacement for git diff
!
Here's a demo:
git diffn
:Create this file:
hello_world.c:
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}
Commit it:
git add hello_world.c
git commit -m "add hello_world.c"
Change it to this and save the file:
hello_world.c:
// Basic hello world example
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Hello Gabriel\n");
int i = 700;
printf("i = %i\n", i);
return 0;
}
Now run:
git diff
Here's the output of git diff
first for comparison purposes:
$ git diff
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+// Basic hello world example
+
#include <stdio.h>
-int main()
+int main(int argc, char *argv[])
{
- printf("Hello World\n");
-
+ printf("Hello Gabriel\n");
+
+ int i = 700;
+ printf("i = %i\n", i);
return 0;
-}
\ No newline at end of file
+}
And a screenshot to show the color. Note that the red highlighted section is simply showing empty whitespace (spaces in this case) that could be deleted:
Now here's the output of git diffn
. Notice it shows all line numbers perfectly!
-
sign on both the far left AND to the right of the :
to help you see better--whether your eyes like to scan down to the right of the colon or down on the far left of the screen.+
sign on both the far left AND to the right of the :
.,
.Output of git diffn
:
$ git diffn
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+ 1:+// Basic hello world example
+ 2:+
1, 3: #include <stdio.h>
2, 4:
- 3 :-int main()
+ 5:+int main(int argc, char *argv[])
4, 6: {
- 5 :- printf("Hello World\n");
- 6 :-
+ 7:+ printf("Hello Gabriel\n");
+ 8:+
+ 9:+ int i = 700;
+ 10:+ printf("i = %i\n", i);
7, 11: return 0;
- 8 :-}
\ No newline at end of file
+ 12:+}
And a screenshot to show the color. Notice that the colons are NOT colored or stylized to match the surrounding text on the left and right. This is intentional and designed-in behavior to act as a visual separator between the line numbers added on the left and the original git diff
output on the right.
meld
as your git difftool
instead. Meld is awesome and I use it waaaay more than git diffn
, though I do use both. Having git diffn
available now though, I pretty much never use git diff
unless I'm on another computer.Here is a script that attempts to fix this - not tested it in anger but it seems ok. It relies on the records git diff produces and uses awk to maintain line counts.
# Massage the @@ counts so they are usable
function prep1() {
cat | awk -F',' 'BEGIN { convert = 0; }
/^@@ / { convert=1; }
/^/ { if ( convert == 1 ) { print $1,$2,$3;
} else { print $0;
}
convert=0;
}'
}
# Extract all new changes added with the line count
function prep2() {
cat | awk 'BEGIN { display=0; line=0; left=0; out=1;}
/^@@ / { out=0; inc=0; line=$4; line--; display=line; left=line; }
/^[-]/ { left++; display=left; inc=0; }
/^[+]/ { line++; display=line; inc=0; }
/^[-+][-+][-+] / { out=0; inc=0; }
/^/ {
line += inc;
left += inc;
display += inc;
if ( out == 1 ) {
print display,$0;
} else {
print $0;
}
out = 1;
inc = 1;
display = line;
}'
}
git diff $1 | prep1 | prep2
A quick way is to use git diff -U0
. That will set the lines of context to 0, which will make the @@ values match the actual changed lines. By default, the @@ values include 3 lines of before/after context, which is not convenient for humans.
Example:
git diff # default
@@ -10,8 +10,8 @@
This is hard to calculate the line numbers of the changed lines because line 10 refers to the first line of the before context. The actual line number of the first changed line is 10+3=13. To calculate the number of changed lines, then you have to also subtract the before and after context: 8-3-3=2.
git diff -U0
@@ -13,2 +13,2 @@
As you can see, setting context = 0 makes the @@ values easier for humans to read. You can see that the changed lines start at line 13, and there are 2 changed lines.
This isn't perfect, since it only shows the line number for each block. If you want to see line numbers for every line, then use difftool for an external editor. See https://stackoverflow.com/a/50049752
You can use git difftool
to do the diff with an external editor that will display line numbers. Here's how to do it with vim / vimdiff:
Set vimdiff as git's difftool:
git config --global diff.tool vimdiff
Configure ~/.vimrc
to automatically show line numbers when using vimdiff:
if &diff
set number
endif
Run git difftool, which will use vimdiff with line numbers:
git difftool
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With