Git khác với số dòng (Git log với số dòng)


92

Khi tôi thực hiện a git diffhoặc a git log -p, làm cách nào để lấy số dòng của (các) tệp nguồn được nội dòng với đầu ra?

Tôi đã cố gắng tìm kiếm nó man git-diff | grep "line numbers"và tôi đã thử googling nhưng không có gì nhanh chóng.

Câu trả lời:


90

Bạn không thể nhận số dòng mà con người có thể đọc được với git diff

Hiện tại không có bất kỳ tùy chọn nào để hiển thị số dòng theo chiều dọc ở bên cạnh git diff.

Định dạng khác biệt thống nhất

Thông tin đó có sẵn trong tiêu đề (c) hunk cho mỗi thay đổi trong khác biệt, tuy nhiên, nó chỉ ở định dạng khác biệt thống nhất :

@@ -start,count +start,count @@

Trạng thái ban đầu của tệp được biểu thị bằng -và trạng thái mới được biểu thị bằng +(chúng không có nghĩa là bổ sung và xóa trong tiêu đề starttệp . Đại diện cho số dòng bắt đầu của mỗi phiên bản tệp và countbiểu thị số dòng được bao gồm , bắt đầu từ điểm xuất phát.

Thí dụ

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

Tiêu đề khúc khuỷu

@@ -11,7 +11,7 @@

nói rằng phiên bản trước của tệp bắt đầu ở dòng 11 và bao gồm 7 dòng:

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

trong khi phiên bản tiếp theo của tệp cũng bắt đầu ở dòng 11 và cũng bao gồm 7 dòng.

Định dạng khác biệt thống nhất không thực sự dành cho con người

Như bạn có thể nói, định dạng thống nhất-khác biệt không giúp bạn dễ dàng tìm ra số dòng (ít nhất là nếu bạn không phải là một cỗ máy). Nếu bạn thực sự muốn số dòng mà bạn có thể đọc được, bạn sẽ cần sử dụng một công cụ khác để hiển thị chúng cho bạn.

Đọc thêm


3
Đây là một grep để giải nén chỉ số dòng trong tập tin sửa đổi, ví dụ như được sử dụng để lọc báo cáo checkstylegit diff --unified=0 | grep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
Jakub Bochenski

1
Bình luận của @ JakubBochenski đã giải quyết vấn đề của tôi khá tốt.
0xbe5077ed 11/09/18

Tuy nhiên, điều này chỉ thực sự hữu ích nếu bạn chỉ định --unified=0hoặc -U0.
caw

Tôi vừa hoàn thành git diffn, một bản thay thế thả vào (trình bao bọc) git diffhiển thị số dòng và có khả năng tương thích hoàn toàn với tất cả cách sử dụng và tùy chọn của git diff: stackoverflow.com/questions/24455377/…
Gabriel Staples

22

Đây là hai giải pháp khác, mở rộng trên mã của Andy Talkowski.

Văn bản thô:

  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}'

Văn bản màu, giả sử \033[66mlà định dạng cho mã màu:

  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}'

Mã thay đổi dòng bắt đầu bằng -+để -1:-+1:+, tương ứng, và dòng bắt đầu với không có gì để (5,6):. Các con số là số dòng từ tệp tương ứng.


Tôi nhận thấy nó phá vỡ sự liên kết (thụt lề) của mã, trong khi bản địa git diffduy trì cẩn thận sự liên kết. Hiện tại, mã này đã qua đầu tôi, vì vậy bạn có sẵn lòng sửa nó không? Nói cách khác, khi một dòng cho biết +240:+và dòng tiếp theo cho biết (241,257):, bạn cần thêm một số khoảng trắng thừa vào dòng trên cùng để làm cho mã của nó duy trì sự liên kết và thụt lề phù hợp với mã từ dòng dưới. Có lẽ điều này có thể dễ dàng được thực hiện với bản in?
Gabriel Staples

... Ý tôi là với printf.
Gabriel Staples


Đừng bận tâm; Tôi hiểu rồi! Tôi vừa hoàn thành git diffn. Xem tại đây: stackoverflow.com/a/61997003/4561887 . Cảm ơn @PFudd, vì câu trả lời của bạn. Tôi đã nghiên cứu nó và sử dụng nó để học, sau đó bắt đầu lại từ đầu và viết git diffn. Sau khi được định dạng để tôi có thể đọc mã của bạn (cảm ơn @EdMorton), tôi đã có thể học được một số điều tuyệt vời từ nó, điều này đã giúp tôi.
Gabriel Staples

6

Đây là một tập lệnh cố gắng khắc phục điều này - không thử nghiệm nó trong cơn giận dữ nhưng nó có vẻ ổn. Nó dựa vào các bản ghi mà git diff tạo ra và sử dụng awk để duy trì số lượng dòng.

# 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

Bạn có thể sử dụng git difftoolđể thực hiện sự khác biệt với trình chỉnh sửa bên ngoài sẽ hiển thị số dòng. Đây là cách thực hiện với vim / vimdiff:

  1. Đặt vimdiff làm git's difftool:

    git config --global diff.tool vimdiff
    
  2. Định cấu hình ~/.vimrcđể tự động hiển thị số dòng khi sử dụng vimdiff:

    if &diff
        set number
    endif
    
  3. Chạy git difftool, sẽ sử dụng vimdiff với số dòng:

    git difftool
    

Bằng cách chỉ thực hiện git difftool, nó đã mở cho tôi công cụ tkdiff, công cụ tự nó có chức năng số dòng. Cảm ơn wisbucky
Richardd

3

Một cách nhanh chóng là sử dụng git diff -U0. Điều đó sẽ đặt các dòng ngữ cảnh thành 0, điều này sẽ làm cho các giá trị @@ khớp với các dòng đã thay đổi thực tế. Theo mặc định, giá trị @@ bao gồm 3 dòng ngữ cảnh trước / sau, điều này không thuận tiện cho con người.

Thí dụ:

git diff # default
@@ -10,8 +10,8 @@

Điều này thật khó để tính toán số dòng của các dòng đã thay đổi vì dòng 10 đề cập đến dòng đầu tiên của ngữ cảnh trước đó. Số dòng thực của dòng thay đổi đầu tiên là 10 + 3 = 13. Để tính số dòng đã thay đổi, bạn cũng phải trừ ngữ cảnh trước và sau: 8-3-3 = 2.

git diff -U0
@@ -13,2 +13,2 @@

Như bạn có thể thấy, việc đặt context = 0 giúp con người đọc các giá trị @@ dễ dàng hơn. Bạn có thể thấy rằng các dòng đã thay đổi bắt đầu từ dòng 13 và có 2 dòng đã thay đổi.

Điều này không hoàn hảo, vì nó chỉ hiển thị số dòng cho mỗi khối. Nếu bạn muốn xem số dòng cho mọi dòng, hãy sử dụng difftool cho trình chỉnh sửa bên ngoài. Xem https://stackoverflow.com/a/50049752


3

Tôi thích sử dụng git difftoolvới meld như difftool tôi. Nó dễ nhìn hơn git diff, có một so sánh gui song song đẹp mắt và hiển thị số dòng ở mỗi bên.

Thiết lập:

  1. Hướng dẫn cách thiết lập meld làm bộ khuếch tán của bạn cho Windows hoặc Linux

Ảnh chụp màn hình mẫu:

nhập mô tả hình ảnh ở đây

Cập nhật ngày 24 tháng 5 năm 2020:

Tôi vừa viết git diffntrong vài ngày qua để được thay thế cho git difftrên dòng lệnh. Cho nó một shot. Xem câu trả lời khác của tôi ở đây .


2

Kể từ ngày 24 tháng 5 năm 2020, bạn hiện có thể sử dụng công cụ của bên thứ ba git diffn(tiết lộ đầy đủ: tôi đã viết) cho mục đích này. Đó là một trình bao bọc mỏng nhẹ xung quanh git diff, được viết bằng awkngôn ngữ lập trình dựa trên mẫu / hành động. Đây là kết quả mẫu khi chạy git diffn:

nhập mô tả hình ảnh ở đây

Đây là bản demo:

1/3: Demo của git diffn:

Tạo tệp này:

hello_world.c:

#include <stdio.h>

int main()
{
    printf("Hello World\n");

    return 0;
}

Cam kết nó:

git add hello_world.c
git commit -m "add hello_world.c"

Thay đổi nó thành này và lưu tệp:

hello_world.c:

// Basic hello world example

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello Gabriel\n");
    
    int i = 700;
    printf("i = %i\n", i);
    return 0;
}

Bây giờ chạy:

git diff

Đây là kết quả git diffđầu tiên cho mục đích so sánh:

$ git diff
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+// Basic hello world example
+
 #include <stdio.h>
 
-int main()
+int main(int argc, char *argv[])
 {
-    printf("Hello World\n");
-
+    printf("Hello Gabriel\n");
+    
+    int i = 700;
+    printf("i = %i\n", i);
     return 0;
-}
\ No newline at end of file
+}

Và một ảnh chụp màn hình để hiển thị màu sắc. Lưu ý rằng phần được đánh dấu màu đỏ chỉ hiển thị khoảng trắng trống (trong trường hợp này là khoảng trắng) có thể bị xóa:

nhập mô tả hình ảnh ở đây

Bây giờ đây là đầu ra của git diffn. Lưu ý rằng nó hiển thị tất cả các số dòng một cách hoàn hảo!

  • Số dòng cho các dòng đã xóa nằm ở bên trái và hiển thị -dấu hiệu ở cả ngoài cùng bên trái VÀ bên phải :để giúp bạn nhìn rõ hơn - cho dù mắt bạn muốn quét xuống bên phải dấu hai chấm hay nhìn xuống phía xa bên trái màn hình.
  • Số dòng cho các dòng được thêm xa hơn về bên phải và hiển thị một +dấu hiệu ở cả phía ngoài cùng bên trái VÀ ở bên phải của :.
  • Số dòng cho các dòng không thay đổi được hiển thị cho ngữ cảnh được hiển thị cho cả bên trái (tệp cũ) VÀ bên phải (tệp mới), được phân tách bằng a ,.

Đầu ra của git diffn:

$ git diffn
diff --git a/hello_world.c b/hello_world.c
index e01704a..e971b73 100644
--- a/hello_world.c
+++ b/hello_world.c
@@ -1,8 +1,12 @@
+        1:+// Basic hello world example
+        2:+
    1,   3: #include <stdio.h>
    2,   4: 
-   3     :-int main()
+        5:+int main(int argc, char *argv[])
    4,   6: {
-   5     :-    printf("Hello World\n");
-   6     :-
+        7:+    printf("Hello Gabriel\n");
+        8:+    
+        9:+    int i = 700;
+       10:+    printf("i = %i\n", i);
    7,  11:     return 0;
-   8     :-}
\ No newline at end of file
+       12:+}

Và một ảnh chụp màn hình để hiển thị màu sắc. Lưu ý rằng các dấu hai chấm KHÔNG được tô màu hoặc cách điệu để phù hợp với văn bản xung quanh ở bên trái và bên phải. Đây là hành vi có chủ đích và được thiết kế để hoạt động như một dấu phân cách trực quan giữa số dòng được thêm vào bên trái và đầu git diffra ban đầu ở bên phải.

nhập mô tả hình ảnh ở đây

2/3: Nó là gì?

Từ đầugit-diffn.sh :

SỰ MIÊU TẢ:

git-diffn.sh

  1. trình thay thế thả vào git diffcũng hiển thị số dòng '! Sử dụng nó giống như chính xácgit diff , ngoại trừ việc bạn sẽ thấy những số dòng đẹp này để giúp bạn hiểu những thay đổi của mình.

  2. vì nó chỉ là một trình bao bọc dựa trên ngôn ngữ awk trọng lượng nhẹ git diff, nó chấp nhận TẤT CẢ các tùy chọn và tham số git diffchấp nhận. Ví dụ:

  3. git diffn HEAD~

  4. git diffn HEAD~3..HEAD~2

  5. hoạt động với bất kỳ git diffcài đặt màu nào của bạn , ngay cả khi bạn đang sử dụng màu tùy chỉnh

  6. Xem câu trả lời của tôi tại đây để biết cách đặt màu khác biệt tùy chỉnh, cũng như để xem ảnh chụp màn hình của đầu ra màu tùy chỉnh từ git diffn: Làm cách nào để bạn tùy chỉnh màu của tiêu đề khác biệt trong git diff?

  7. Dưới đây là một số git configlệnh mẫu từ câu trả lời của tôi ở trên để đặt git diffmàu và thuộc tính tùy chỉnh (định dạng văn bản):

       git config --global color.diff.meta "blue"
       git config --global color.diff.old "black red strike"
       git config --global color.diff.new "black green italic"
       git config --global color.diff.context "yellow bold"
    
  8. trong git diffn, đầu ra màu được BẬT theo mặc định; nếu bạn muốn tắt màu đầu ra, bạn phải sử dụng --no-colorhoặc --color=never. Xem man git diffđể biết chi tiết. Ví dụ:

     git diffn --color=never HEAD~
     git diffn --no-color HEAD~3..HEAD~2
    

3/3: Cài đặt

  1. Windows (chưa được kiểm tra): điều này có thể hoạt động bên trong bash terminal đi kèm với Git dành cho Windows , nhưng chưa được kiểm tra. Cài đặt Git cho Windows. Mở thiết bị đầu cuối bash đi kèm và thử làm theo hướng dẫn bên dưới. Tôi cần một số người kiểm tra sẽ kiểm tra điều này trong Git cho Windows. Mời các bạn xem và trả lời tại đây: https://github.com/git-for-windows/git/issues/2635 .
  2. Mac (chưa được kiểm tra): sử dụng thiết bị đầu cuối và làm theo hướng dẫn bên dưới. Bạn có thể cần phải cài đặt gawk. Nếu vậy, hãy thử này : brew install gawk.
  3. Linux (đã thử nghiệm trên Ubuntu 18.04 và hoạt động hoàn hảo): làm theo hướng dẫn đầu cuối bên dưới.

Tùy chọn 1 (đề xuất của tôi): tải xuống toàn bộ repo và sau đó tạo một liên kết tượng trưng cho chương trình để bạn có thể dễ dàng nhận các bản cập nhật bằng cách thực hiện một git pulltừ repo bất cứ khi nào bạn muốn.

Đầu tiên, cdđến bất cứ nơi nào bạn muốn cài đặt cái này. Sau đó chạy:

git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-diffn.sh" ~/bin/git-diffn

Làm xong! Bây giờ chỉ cần thực hiện bước cuối cùng bên dưới!

Tùy chọn 2 (dành cho những người chỉ muốn 1 tệp): chỉ tải xuống một tệp một lần.

mkdir -p ~/bin
cd ~/bin
wget https://raw.githubusercontent.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/master/useful_scripts/git-diffn.sh
chmod +x git-diffn.sh
mv git-diffn.sh git-diffn

Làm xong! Bây giờ chỉ cần thực hiện bước cuối cùng bên dưới!

Bước cuối cùng:

Bây giờ, hãy đóng và mở lại thiết bị đầu cuối của bạn hoặc cấp nguồn lại bằng . ~/.bashrcvà bạn đã hoàn tất!

git diffnbây giờ sẽ hoạt động như một sự thay thế chính xác cho git diff!


1

Bạn co thể thử

git blame

trên tệp. Nó hiển thị cho bạn trình cam kết, id cam kết và số dòng cho mỗi dòng trong tệp.


4
Vấn đề với điều này là nó không hiển thị cho bạn một sự khác biệt , đó là những gì người đăng ban đầu yêu cầu. git blamesẽ chỉ hiển thị trạng thái hiện tại của tệp với số dòng.

5
Tôi biết về lỗi git, nhưng ai đó googling có thể không có. Nó có thể giúp ai đó. Cảm ơn vì đã trả lời.
Drew LeSueur

git blamekhông có cách nào trả lời câu hỏi; Tôi khá bối rối trước những lời tán thành ở đây
Michael Mrozek

Vui lòng không spam luồng stackover với các câu trả lời không liên quan đến câu hỏi.
Ahmed

0

Đầu tiên, hãy cấu hình công cụ git diff của bạn, ví dụ: Meld

git config --global diff.tool meld

Sau đó, kéo bộ khuếch tán của bạn trên một số tệp:

git difftool -y config.rb

Hãy nhớ thiết lập số dòng trong tùy chọn công cụ khác biệt của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.