问题
When I do a git diff
or a git log -p
, how do I get line numbers of the source file(s) inlined with the output?
I tried to look it up man git-diff | grep "line numbers"
and I tried googling but got nothing quickly.
回答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
回答2:
Here's two more solutions, 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];right=a[2];next};\
/^(---|\+\+\+|[^-+ ])/{print;next};\
{line=substr($0,2)};\
/^-/{print "-" left++ ":" line;next};\
/^[+]/{print "+" right++ ":" line;next};\
{print "(" left++ "," right++ "):"line}'
Colored text, assuming \033[66m
is the format for color codes:
git diff --color=always | \
gawk '{bare=$0;gsub("\033[[][0-9]*m","",bare)};\
match(bare,"^@@ -([0-9]+),[0-9]+ [+]([0-9]+),[0-9]+ @@",a){left=a[1];right=a[2];next};\
bare ~ /^(---|\+\+\+|[^-+ ])/{print;next};\
{line=gensub("^(\033[[][0-9]*m)?(.)","\\2\\1",1,$0)};\
bare~/^-/{print "-"left++ ":" line;next};\
bare~/^[+]/{print "+"right++ ":" line;next};\
{print "("left++","right++"):"line;next}'
The code changes lines that start with -
or +
to -1:-
or +1:+
, and lines that start with to
(5,6):
. The numbers are the line numbers from the respective file.
回答3:
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
回答4:
You can try
git blame
on the file. It shows you the committer, commit id, and line number for each line in the file.
回答5:
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
回答6:
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
回答7:
I like to use git difftool
with meld as my difftool. It's easier to look at than git diff
, has a nice side-by-side gui comparison, and shows line numbers.
来源:https://stackoverflow.com/questions/24455377/git-diff-with-line-numbers-git-log-with-line-numbers