2011-11-24 25 views
52

Giả sử tôi có một tập tin văn bảnSử dụng git diff, làm thế nào tôi có thể nhận được số dòng bổ sung và sửa đổi?

alex 
bob 
matrix 
will be removed 
git repo 

và tôi đã cập nhật nó được

alex 
new line here 
another new line 
bob 
matrix 
git 

Ở đây, tôi đã thêm số dòng (2,3) và cập nhật số dòng (6)

Làm cách nào để có được thông tin số dòng này bằng cách sử dụng git diff hoặc bất kỳ lệnh git nào khác?

Trả lời

47

git diff --stat sẽ hiển thị cho bạn kết quả bạn nhận được khi cam kết nội dung mà bạn đang đề cập đến tôi đoán.

git diff --stat 

Đối với thể hiện chính xác số dòng mà đã được thay đổi, bạn có thể sử dụng

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

Và dòng thay đổi sẽ là số cuối cùng trước khi ngoặc kết thúc bằng kết quả. . Không phải là một giải pháp làm sạch mặc dù :(

+1

stat chỉ hiển thị có bao nhiêu dòng được chèn/xóa/cập nhật. Nhưng tôi cần phải biết những con số dòng –

+0

Điều này dường như là một vấn đề khó hơn nó nên được, nhưng tôi quản lý để có được nó bằng cách sử dụng git đổ lỗi và grep.Xem câu trả lời cập nhật của tôi – Sedrik

+1

Người ta thường gọi 'git blame -p' nếu đầu ra được xử lý bởi các chương trình khác như 'awk' hoặc 'grep'. –

1

Configure một công cụ diff bên ngoài mà sẽ cho bạn thấy số dòng Ví dụ, đây là những gì tôi có trong git config toàn cầu của tôi:

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" 

Xem câu trả lời này để biết thêm chi tiết: https://stackoverflow.com/q/949242/526535

+0

không có cách nào khác để có được những thông tin này mà không cần sử dụng công cụ khác. Chỉ sử dụng lệnh git? –

0

Không chính xác những gì bạn đã yêu cầu, nhưng git blame TEXTFILE có thể giúp

23

Dưới đây là một chức năng bash để tính toán số dòng kết quả từ một 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 
} 

Nó có thể sản xuất ra như:

$ 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); 

từ một diff như thế này:

$ 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); 

Nếu bạn chỉ muốn hiển thị thêm/gỡ bỏ/dòng sửa đổi, và không phải là xung quanh ngữ cảnh, bạn có thể vượt qua -U0 để 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); 

Nó mạnh mẽ chống lại mã màu ANSI, vì vậy bạn có thể vượt qua --color=always để git diff để có được mã hóa màu thông thường cho các dòng được thêm/xóa.

Sản lượng có thể dễ dàng 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); 

Trong trường hợp của bạn git diff -U0 sẽ cung cấp cho:

$ 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 

Nếu bạn chỉ muốn những con số dòng, thay đổi echo "$path:$line:$REPLY" chỉ echo "$line" và ống đầu ra thông qua uniq.

+0

Làm cách nào tôi có thể chuyển mã thoát màu bash? Điều này thật tuyệt vời, nhưng các mã màu đến từ 'git diff --color' không đi qua. Hay bạn nghĩ sẽ tốt hơn nếu chỉ thêm màu thoát vào sự trở lại của hàm này? –

+2

Tôi đã cập nhật hàm để các regex khác nhau mạnh mẽ đối với các mã màu ANSI. 'git diff --color | diff-lines' hiện hoạt động như mong đợi :) –

+0

Giải pháp này hoạt động tuyệt vời! nó phải được đánh dấu là câu trả lời vì nó thực sự làm những gì OP hỏi. Nếu nó làm việc cho bạn xin vui lòng bỏ phiếu cho nó để chúng tôi có thể làm cho nó câu trả lời phổ biến :) – markdrake

1

Dưới đây là một chức năng bash tôi gom góp:

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 

Và nó kết thúc lên tim như thế này:

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

Bạn có thể sử dụng git diff cùng với shortstat tham số để chỉ hiển thị các không của dòng đã thay đổi.

Đối với không có dòng thay đổi (trong một tập tin đó là đã có trong repo) kể từ lần cuối bạn cam kết

git diff HEAD --shortstat 

nó sẽ một cái gì đó đầu ra tương tự như

1 file changed, 4 insertions(+) 
6

Tôi có vấn đề này cùng vì vậy tôi đã viết một tập lệnh gawk thay đổi đầu ra của git diff để thêm số dòng cho mỗi dòng. Đôi khi tôi thấy nó hữu ích khi tôi cần cây làm việc khác, mặc dù nó không giới hạn ở đó. Có lẽ nó hữu ích cho ai đó ở đây?

$ 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 

Bạn có thể tải về từ đây:
https://github.com/jay/showlinenum

+0

Trông rất tiện dụng. Hãy nhớ rằng mã này có lợi thế (hoặc bất lợi) khi được cấp phép GPL. – BlackVegetable

0

Đây có lẽ là một số khá chính xác của dòng thay đổi:

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

Ngoài ra, đây là một giải pháp cho số dòng trong của bạn khác: https://github.com/jay/showlinenum

11

Tôi sử dụng tùy chọn --unified=0git diff.

Ví dụ, kết quả đầu ra git diff --unified=0 commit1 commit2 diff:

*enter image description here*

Do tùy chọn --unified=0, sản lượng diff cho thấy 0 dòng bối cảnh; nói cách khác, nó hiển thị chính xác các dòng đã thay đổi.

Bây giờ, bạn có thể xác định các dòng bắt đầu bằng '@@', và phân tích nó dựa trên các mô hình:

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

Quay lại ví dụ trên, cho các tập tin WildcardBinding.java, bắt đầu từ dòng 910, 0 dòng bị xóa. Bắt đầu từ dòng 911, 4 dòng được thêm vào.

+0

nếu '@@ -910,10, + 911,15 @@' hoặc gì đó, thì làm cách nào để chúng tôi nói chính xác số lượng dòng được thêm, xóa hoặc sửa đổi –

3

số dòng của tất cả các dòng không bị giam (thêm/sửa đổi):

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

Ví dụ đầu ra:

1 
2 
8 
12 
13 
14 
+0

nội dung của các dòng đã được thay đổi như thế nào tốt? – anon58192932

Các vấn đề liên quan