Here's a bash function to calculate the resulting line numbers from a diff:
diff-lines() { local esc=$'\e' local ansi=$'\e\\[[0-9;]*m' local REPLY= local path= local line= # For each line in stdin... while IFS= read -r || [[ -n $REPLY ]]; do # ...match the start of the line, ignoring leading ANSI escapes. if [[ $REPLY =~ ^($ansi)*---\ (a/)?.* ]]; then continue elif [[ $REPLY =~ ^($ansi)*\+\+\+\ (b/)?([^[:blank:]$esc]+).* ]]; then path=${BASH_REMATCH[3]} elif [[ $REPLY =~ ^($ansi)*@@\ -[0-9]+(,[0-9]+)?\ \+([0-9]+)(,[0-9]+)?\ @@.* ]]; then line=${BASH_REMATCH[3]} elif [[ $REPLY =~ ^($ansi)*([\ +-\\]) ]]; 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); fetch.h:7:\ No newline at end of file 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); \ No newline at end of file +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); fetch.h:7:-bool fetch_succeeded(int status_code); fetch.h:7:\ No newline at end of file fetch.h:7:+bool fetch_succeeded(int status_code);
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.