Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git diff to show only lines that have been modified

Tags:

git

diff

People also ask

How do I see changes in git diff?

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.

Why git diff does not show changes?

Your file is already staged to be committed. You can show it's diff using the --cached option of git. To unstage it, just do what git status suggests in it's output ;) You can check The Git Index For more info.

What does git diff show you?

The git diff command shows the differences between the files in two commits or between your current repository and a previous commit. This command displays changes denotes by headers and metadata for the files that have changed.


What you want is a diff with 0 lines of context. You can generate this with:

git diff --unified=0

or

git diff -U0

You can also set this as a config option for that repository:

git config diff.context 0

To have it set globally, for any repository:

 git config --global diff.context 0

Another hack (on un*x) to show just the lines beginning with + and -:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

The code above does the following:

  • git diff -U0: choose 0 context lines
  • The first grep only includes all lines starting with + or -
  • The second grep excludes lines starting with --- a/ or +++ b/

Color

To show colored diff, try the following:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • The expression, ^\e\[[^m]*m[-+], looks for start of line (^), then the escape characer (\e) followed by [ which together start the escape sequence, then any character that is not an "m" (numbers, semicolons, or nothing), followed by an "m" which ends the escape sequence.
  • Note that all of the following are valid escape sequences: \e[0m (reset), \e[m (also reset), \e[1m (bold on), \e[31m (red), \e[32m (green), \e[9;31m (strike out + red), \e[31;9m (red + strike out), \e[1;4;9;31m (bold + underline + strike out + red). The default git colors use red and green, but they can be reconfigured.
  • --color is the same as --color=always.
  • The restriction on --- a/ or +++ b/ to appear at the start of the line has been removed to accommodate for the escape sequences and this could lead to an edge case.

Additional Notes:

  • The above solution needs to be modified if you use additional git diff options such as -R, --src-prefix, --dst-prefix, --no-prefix, etc.
  • The two greps can be combined into a single grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', but I find the double grep version easier to understand.

I think for simple cases the regex can be much shorter and easier to remember, with the caveat that this won't work if you have line changes where the line itself starts with + or -

$ git diff | grep '^[+|-][^+|-]'

The regex says the line should start with + or -, and the immediately following character should be neither of those. I got the same results whether I escaped the + or not here, btw...


Example:

$ cat testfile
A
B
C
D
E
F
G

Say I change C to X, E to Y, and G to Z.

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

Like I said above, though, this is just for most cases. If you pipe that output to a file dout, then try the same regex, it won't work.

$ git diff dout | grep '^[+|-][^+|-]'
$

Anyways, hope that helps in your case


Following up on Chris' latest comment, the main problem with the post-processing is that you want to keep lines starting with -|+ but you also want to filter out those that start with ---|+++. If you are storing patch files in your repo (I do, in Pydoop), on the other hand, you want to keep lines that start with --|++, so the regexp becomes a bit involved:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

The regexp uses a negative lookahead: see Peter Boughton's answer to this question for a detailed explanation.

If you do this often, you might want to set up a git alias for it:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'