Using git diff, how can I get added and modified lines numbers?

给你一囗甜甜゛ 提交于 2019-11-26 15:20:30

问题


Assuming I have a text file

alex bob matrix will be removed git repo 

and I have updated it to be

alex new line here another new line bob matrix git 

Here, I have added lines number (2,3) and updated line number (6)

How can I get these line numbers info using git diff or any other git command?


回答1:


git diff --stat will show you the output you get when committing stuff which is the one you are referring to I guess.

git diff --stat 

For showing exactly the line numbers that has been changed you can use

git blame -p <file> | grep "Not Committed Yet" 

And the line changed will be the last number before the ending parenthesis in the result. Not a clean solution though :(




回答2:


Here's a bash function to calculate the resulting line numbers from a diff:

diff-lines() {     local path=     local line=     while read; do         esc=$'\033'         if [[ $REPLY =~ ---\ (a/)?.* ]]; then             continue         elif [[ $REPLY =~ \+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then             path=${BASH_REMATCH[2]}         elif [[ $REPLY =~ @@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then             line=${BASH_REMATCH[2]}         elif [[ $REPLY =~ ^($esc\[[0-9;]+m)*([\ +-]) ]]; then             echo "$path:$line:$REPLY"             if [[ ${BASH_REMATCH[2]} != - ]]; then                 ((line++))             fi         fi     done } 

It can produce output such as:

$ git diff | diff-lines http-fetch.c:1: #include "cache.h" http-fetch.c:2: #include "walker.h" http-fetch.c:3:  http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix) http-fetch.c:4:+int main(int argc, const char **argv) http-fetch.c:5: { http-fetch.c:6:+       const char *prefix; http-fetch.c:7:        struct walker *walker; http-fetch.c:8:        int commits_on_stdin = 0; http-fetch.c:9:        int commits; http-fetch.c:19:        int get_verbosely = 0; http-fetch.c:20:        int get_recover = 0; http-fetch.c:21:  http-fetch.c:22:+       prefix = setup_git_directory(); http-fetch.c:23:+ http-fetch.c:24:        git_config(git_default_config, NULL); http-fetch.c:25:  http-fetch.c:26:        while (arg < argc && argv[arg][0] == '-') { fetch.h:1: #include "config.h" fetch.h:2: #include "http.h" fetch.h:3:  fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix); fetch.h:4:+int main(int argc, const char **argv); fetch.h:5:  fetch.h:6: void start_fetch(const char* uri); fetch.h:7: bool fetch_succeeded(int status_code); 

from a diff like this:

$ git diff diff --git a/builtin-http-fetch.c b/http-fetch.c similarity index 95% rename from builtin-http-fetch.c rename to http-fetch.c index f3e63d7..e8f44ba 100644 --- a/builtin-http-fetch.c +++ b/http-fetch.c @@ -1,8 +1,9 @@  #include "cache.h"  #include "walker.h"  -int cmd_http_fetch(int argc, const char **argv, const char *prefix) +int main(int argc, const char **argv)  { +       const char *prefix;         struct walker *walker;         int commits_on_stdin = 0;         int commits; @@ -18,6 +19,8 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix)         int get_verbosely = 0;         int get_recover = 0;  +       prefix = setup_git_directory(); +         git_config(git_default_config, NULL);          while (arg < argc && argv[arg][0] == '-') { diff --git a/fetch.h b/fetch.h index 5fd3e65..d43e0ca 100644 --- a/fetch.h +++ b/fetch.h @@ -1,7 +1,7 @@  #include "config.h"  #include "http.h"  -int cmd_http_fetch(int argc, const char **argv, const char *prefix); +int main(int argc, const char **argv);   void start_fetch(const char* uri);  bool fetch_succeeded(int status_code); 

If you only want to show added/removed/modified lines, and not the surrounding context, you can pass -U0 to git diff:

$ git diff -U0 | diff-lines http-fetch.c:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix) http-fetch.c:4:+int main(int argc, const char **argv) http-fetch.c:6:+       const char *prefix; http-fetch.c:22:+       prefix = setup_git_directory(); http-fetch.c:23:+ fetch.h:4:-int cmd_http_fetch(int argc, const char **argv, const char *prefix); fetch.h:4:+int main(int argc, const char **argv); 

It's robust against ANSI color codes, so you can pass --color=always to git diff to get the usual color coding for added/removed lines.

The output can be easily grepped:

$ git diff -U0 | diff-lines | grep 'main' http-fetch.c:4:+int main(int argc, const char **argv) fetch.h:4:+int main(int argc, const char **argv); 

In your case git diff -U0 would give:

$ git diff -U0 | diff-lines test.txt:2:+new line here test.txt:3:+another new line test.txt:6:-will be removed test.txt:6:-git repo test.txt:6:+git 

If you just want the line numbers, change the echo "$path:$line:$REPLY" to just echo "$line" and pipe the output through uniq.




回答3:


I use the --unified=0 option of git diff.

For example, git diff --unified=0 commit1 commit2 outputs the diff:

Because of the --unified=0 option, the diff output shows 0 context lines; in other words, it shows exactly the changed lines.

Now, you can identify the lines that start with '@@', and parse it based on the pattern:

@@ -startline1,count1 +startline2,count2 @@

Back to the above example, for the file WildcardBinding.java, start from line 910, 0 lines are deleted. Start from line 911, 4 lines are added.




回答4:


I had this same problem so I wrote a gawk script that changes the output of git diff to prepend the line number for each line. I find it useful sometimes when I need to diff working tree, although it's not limited to that. Maybe it is useful to someone here?

$ git diff HEAD~1 |showlinenum.awk diff --git a/doc.txt b/doc.txt index fae6176..6ca8c26 100644 --- a/doc.txt +++ b/doc.txt @@ -1,3 +1,3 @@ 1: red 2: blue  :-green 3:+yellow 

You can download it from here:
https://github.com/jay/showlinenum




回答5:


Line numbers of all uncommitted lines (added/modified):

git blame <file> | grep -n '^0\{8\} ' | cut -f1 -d: 

Example output:

1 2 8 12 13 14 



回答6:


Configure an external diff tool which will show you the line numbers. For example, this is what I have in my git global config:

diff.guitool=kdiff3 difftool.kdiff3.path=c:/Program Files (x86)/KDiff3/kdiff3.exe difftool.kdiff3.cmd="c:/Program Files (x86)/KDiff3/kdiff3.exe" "$LOCAL" "$REMOTE" 

See this answer for more details: https://stackoverflow.com/q/949242/526535




回答7:


Here's a bash function I cobbled together:

echo ${f}: for n in $(git --no-pager blame --line-porcelain $1 |         awk '/author Not Committed Yet/{if (a && a !~ /author Not Committed Yet/) print a} {a=$0}' |         awk '{print $3}') ; do     if (( prev_line > -1 )) ; then         if (( "$n" > (prev_line + 1) )) ; then             if (( (prev_line - range_start) > 1 )) ; then                 echo -n "$range_start-$prev_line,"             else                 echo -n "$range_start,$prev_line,"             fi             range_start=$n         fi     else         range_start=$n     fi     prev_line=$n done if (( "$range_start" != "$prev_line" )) ; then     echo "$range_start-$prev_line" else     echo "$range_start" fi 

And it ends up looking like this:

views.py: 403,404,533-538,546-548,550-552,554-559,565-567,580-582 



回答8:


You can use git diff coupled with shortstat parameter to just show the no of lines changed.

For the no of lines changed (in a file that's already in the repo) since your last commit

git diff HEAD --shortstat 

It'll output something similar to

1 file changed, 4 insertions(+) 



回答9:


Not exactly what you were asking for, but git blame TEXTFILE may help.




回答10:


This is probably a fairly accurate count of changed lines:

git diff --word-diff <commit> |egrep '(?:\[-)|(?:\{\+)' |wc -l 

Also, here is a solution for line numbers in your diff: https://github.com/jay/showlinenum



来源:https://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!