Git diff chỉ hiển thị các dòng đã được sửa đổi


128

Khi tôi thực hiện một git diff, nó hiển thị các dòng đã được thêm vào:

+ this line is added

các dòng đã bị xóa:

- this line is removed

nhưng nó cũng hiển thị nhiều dòng không được sửa đổi:

this line is not modified
this line is also not modified

Điều này dẫn đến git diff thực tế trông giống như thế này:

+ this line is added
  this line is not modified
- this line is removed
  this line is not modified

Tôi có thể yêu cầu git chỉ hiển thị các dòng đã được sửa đổi và bỏ qua tất cả các mã khác chưa được sửa đổi không? Tôi đã viết một phương thức sẽ loại bỏ tất cả các dòng không có dấu "+" hoặc "-" trước chúng, nhưng tôi chắc chắn phải có một cách đơn giản hơn để làm điều này.

Trong git diff của tôi, tôi chỉ quan tâm đến việc xem các dòng đã được sửa đổi.

Cảm ơn trước.

Câu trả lời:


182

Những gì bạn muốn là một khác biệt với 0 dòng bối cảnh. Bạn có thể tạo cái này với:

git diff --unified=0

hoặc là

git diff -U0

Bạn cũng có thể đặt tùy chọn này làm tùy chọn cấu hình cho kho lưu trữ đó:

git config diff.context 0

Để thiết lập nó trên toàn cầu, cho bất kỳ kho lưu trữ nào:

 git config --global diff.context 0

4
Cảm ơn đã trã lời nhanh chóng. Điều này giải quyết được một nửa vấn đề của tôi nhưng tôi vẫn nhận được một số dòng như "@@ -1 +1 @@" trong diff và đầu git diff của tôi có "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t

3
Tôi không nghĩ git cung cấp bất kỳ cách nào để tránh xuất ra những dòng đó, bởi vì diff sẽ không có ý nghĩa nếu không có chúng (bạn không thể biết bạn đang xem tập tin nào, cũng như bạn đang ở đâu trong tập tin).
Chris Hayes

8
@Rakesh: Để mở rộng, git-diff cố gắng tạo ra các khác biệt thực sự có thể được sử dụng làm bản vá cho các tệp nguồn, điều này là không thể nếu không có thông tin đó. Cách duy nhất để loại bỏ nó là tự xử lý hậu kỳ, chẳng hạn như thông qua git diff | egrep "^(\+|-) ".
Chris Hayes

1
git config --global diff.context 0 để thiết lập nó trên toàn cầu
Andrzej Rehmann

Nếu bạn muốn xem trong một thư mục cụ thể, hãy thử git diff -U0 <dir>
Eswar Yaganti

41

Một hack khác (trên un * x) để chỉ hiển thị các dòng bắt đầu bằng +-:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

Đoạn mã trên thực hiện như sau:

  • git diff -U0: chọn 0 dòng ngữ cảnh
  • Grep đầu tiên chỉ bao gồm tất cả các dòng bắt đầu bằng +hoặc-
  • Grep thứ hai loại trừ các dòng bắt đầu bằng --- a/hoặc+++ b/

Màu sắc

Để hiển thị màu khác nhau, hãy thử như sau:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • Biểu thức, ^\e\[[^m]*m[-+]tìm kiếm bắt đầu của dòng ( ^), sau đó là characer thoát ( \e) theo sau [đó cùng nhau bắt đầu chuỗi thoát, sau đó bất kỳ ký tự nào không phải là "m" (số, dấu chấm phẩy hoặc không có gì), theo sau là " m "kết thúc chuỗi thoát.
  • Lưu ý rằng tất cả những điều sau đây là các chuỗi thoát hợp lệ: \e[0m(đặt lại), \e[m(cũng đặt lại), \e[1m(in đậm), \e[31m(đỏ), \e[32m(xanh lục), \e[9;31m(tấn công + đỏ), \e[31;9m(đỏ + tấn công), \e[1;4;9;31m(đậm + gạch chân + tấn công + đỏ). Các màu git mặc định sử dụng màu đỏ và màu xanh lá cây, nhưng chúng có thể được cấu hình lại.
  • --colorcũng giống như --color=always.
  • Hạn chế trên --- a/hoặc +++ b/xuất hiện ở đầu dòng đã được gỡ bỏ để phù hợp với các chuỗi thoát và điều này có thể dẫn đến trường hợp cạnh.

Ghi chú bổ sung:

  • Các giải pháp trên cần phải được sửa đổi nếu bạn sử dụng thêm tùy chọn git diff như -R, --src-prefix, --dst-prefix, --no-prefixvv
  • Hai greps có thể được kết hợp thành một grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )', nhưng tôi thấy phiên bản grep đôi dễ hiểu hơn.

2
Đẹp một. Upvote cho lời giải thích rõ ràng trên mỗi bộ lọc.
henrebotha

Tôi thấy rất nhiều git diffdòng loại "tiêu đề" bắt đầu bằng @@, nhưng git diffdòng nào bắt đầu bằng ---hoặc +++? Tôi đã không biết về những người đó.
Gabriel Staples

À, đừng bận tâm. Những biểu thị tên tệp cho các tệp có chứa bổ sung ( +++) hoặc xóa ( ---). Bây giờ tôi thấy điều đó ở đây: git-scm.com/docs/git-diff#_combined_diff_format .
Gabriel Staples

Sửa lỗi một lần nữa: --- a/filenamedường như biểu thị "tệp ở bên trái" hoặc tệp như trước đây và +++ b/filenamedường như biểu thị "tệp ở bên phải" hoặc tệp như hiện tại với các thay đổi của bạn. Tôi đã quá quen với việc sử dụng git difftoolvới meld , điều này cho thấy sự so sánh song song tuyệt đẹp, mà tôi chưa bao giờ thực sự quen với việc nhìn vào git diff, vì vậy nó vẫn trông lạ đối với tôi, và tôi chưa bao giờ thực sự nhìn vào những sắc thái này trước đây.
Gabriel Staples

1
@GabrielStaples, hỗ trợ cho màu sắc đã được thêm vào. Cảm ơn.
dùng650654

6

Theo dõi bình luận mới nhất của Chris, vấn đề chính của quá trình xử lý hậu kỳ là bạn muốn giữ các dòng bắt đầu -|+nhưng bạn cũng muốn lọc ra những dòng bắt đầu bằng ---|+++. Nếu bạn đang lưu trữ các tệp vá trong repo của mình (tôi làm, trong Pydoop ), mặt khác, bạn muốn giữ các dòng bắt đầu bằng --|++, vì vậy regrec trở nên hơi liên quan:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

Regrec sử dụng một cái nhìn tiêu cực: xem câu trả lời của Peter Boughton cho câu hỏi này để được giải thích chi tiết.

Nếu bạn làm điều này thường xuyên, bạn có thể muốn thiết lập bí danh git cho nó:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'

1
Điều này không làm việc cho tôi trên Windows git bash. Không biết tại sao (grep nói tùy chọn P không hợp lệ), không có chutzpah để xem xét tại thời điểm này.
Dennis

1
-Phoặc --perl-regexpđược sử dụng để giải thích mô hình như một sự tái hiện thường xuyên của Perl, nhưng không phải lúc nào cũng được thực hiện. Nó không hoạt động với tôi trên OSX. gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega

4

Tôi nghĩ đối với các trường hợp đơn giản, biểu thức chính quy có thể ngắn hơn và dễ nhớ hơn nhiều, với lời cảnh báo rằng điều này sẽ không hoạt động nếu bạn có các thay đổi dòng trong đó chính dòng bắt đầu bằng +hoặc-

$ git diff | grep '^[+|-][^+|-]'

Regex nói rằng dòng nên bắt đầu bằng +hoặc -, và ký tự ngay sau đó không phải là ký tự. Tôi đã nhận được kết quả tương tự cho dù tôi có thoát được +hay không ở đây, btw ...


Thí dụ:

$ cat testfile
A
B
C
D
E
F
G

Nói rằng tôi thay đổi Cđể X, Eđến Y, và Gđể Z.

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

Như tôi đã nói ở trên, mặc dù, điều này chỉ dành cho hầu hết các trường hợp. Nếu bạn chuyển đầu ra thành một tệp dout, sau đó thử regex tương tự, nó sẽ không hoạt động.

$ git diff dout | grep '^[+|-][^+|-]'
$

Dù sao, hy vọng rằng sẽ giúp trong trường hợp của bạn


Đối với trường hợp dòng bắt đầu bằng "-" thì nó sẽ không hoạt động. Ví dụ: - name: No pdbtrong một tệp yaml.
anapaulagomes

3

Câu trả lời này sẽ giữ lại màu đỏ / xanh ban đầu để dễ đọc. Tôi đã cung cấp một vài biến thể trong cú pháp:

git diff --color | grep --color=never $'^\e\[3[12]m'
git diff --color | grep --color=never $'^\033\[3[12]m'
git diff --color | grep --color=never -P '^\e\[3[12]m'
git diff --color | grep --color=never -P '^\033\[3[12]m'

Giải trình:

  • Điều git diff --colornày là cần thiết để ngăn git vô hiệu hóa màu sắc khi nó là đường ống.
  • Điều grep --color=nevernày là để ngăn grep loại bỏ màu gốc và làm nổi bật chuỗi phù hợp.
  • Chúng tôi phù hợp với các dòng bắt đầu bằng mã thoát màu đỏ ( \e[31m) hoặc xanh lục ( \e[32m).
  • Các $'...'(ANSI-C cú pháp trích dẫn) hoặc -P(cú pháp perl) là để cho grepđể giải thích \ehoặc \033như một ESCnhân vật.

Cảm ơn vì điều đó. Đây là một hình thức thay thế mà tôi vừa nghĩ ra. Phần của bạn $''đặc biệt giúp tôi. stackoverflow.com/a/61929887/4561887
Gabriel Staples

1

Cách sử dụng awkđể chỉ hiển thị +-các dòng, tính toán cho bất kỳ định dạng màu hoặc văn bản nào git diffcó thể xuất ra:

Không một câu trả lời nào khác ở đây (bao gồm cả câu trả lời khác của tôi ) sẽ thực hiện chính xác những gì bạn muốn chính xác 100%. Câu trả lời này, tuy nhiên, sẽ. Đây là 1 lớp lót bạn có thể sao chép và dán vào thiết bị đầu cuối của mình. Tôi vừa tạo cho nó nhiều dòng để dễ đọc - bạn có thể sao chép-dán nó theo cùng một cách để tôi cũng có thể đọc được! Nó dựa vào awkngôn ngữ lập trình:

git diff --color=always "$@" | awk '
# 1. Match and then skip "--- a/" and "+++ b/" lines
/^(\033\[(([0-9]{1,2};?){1,10})m)?(--- a\/|\+\+\+ b\/)/ {
    next 
} 
# 2. Now print the remaining "+" and "-" lines ONLY! Note: doing step 1 above first was required or
# else those lines would have been matched by this matcher below too since they also begin with 
# the "+" and "-" symbols.
/^(\033\[(([0-9]{1,2};?){1,10})m)?[-+]/ {
    print $0 
}
' | less -RFX

Dưới đây là các tính năng của nó. Tất cả các tính năng này, khi được thực hiện cùng nhau, giải quyết các thiếu sót của mọi câu trả lời khác ở đây:

  1. Nó xử lý màu VÀ đầu ra không màu. Đó là những gì biểu hiện thường xuyên này làm:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. Nó xử lý TẤT CẢ MÀU SẮC và TẤT CẢ CÁC LỰA CHỌN VĂN BẢN, bao gồm in đậm, in nghiêng, gạch ngang, v.v., mà bạn có thể đặt trong git configcài đặt của mình . Đó là lý do tại sao regex ở trên có ;?{1,10}trong đó: nếu nó phát hiện sự bắt đầu của mã định dạng màu hoặc văn bản, nó sẽ khớp với tối đa 10 chuỗi các mã ANSI kết hợp này.
  3. Nó cũng không bao gồm các dòng bắt đầu bằng @@và từ diff, như câu trả lời được chấp nhận . Nếu bạn muốn những dòng đó (khá thẳng thắn, tôi nghĩ là hữu ích :)), hãy làm điều này thay vào đó:

    git diff --unified=0
    

    hoặc là

    git diff -U0
    
  4. Nó hiển thị đầu ra theo cách chính xác như git diffsau: trong lessmáy nhắn tin có đầu ra màu tùy chọn ( -R) và chỉ khi văn bản> 1 trang ( -F) và trong khi giữ lại trang văn bản hiện tại trên màn hình khi bạn quit ( -X) .

Nó cũng có lợi ích là mạnh mẽ và dễ dàng cấu hình vì nó sử dụng ngôn ngữ lập trình awk.

Nếu bạn quan tâm đến việc học awk , đây là một số tài nguyên:

  1. gawk(GNU awk) hướng dẫn sử dụng: https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. Nghiên cứu git diffnvà nhận xét trong đó: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/usiously_scripts/git-diffn.sh
    1. Nếu bạn git diffncũng muốn , đó là git diffvới số dòng, xem tại đây: Git diff với số dòng (Nhật ký Git với số dòng)
  3. Một số ví dụ kiểm tra cú pháp "hello world" và cú pháp: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

Như một phần thưởng, tôi cũng gói gọn những thứ ở trên để sử dụng git diffc, có nghĩa là "git diff để hiển thị CHỈ". Cách sử dụng là giống hệt nhau để git diff; chỉ sử dụng git diffcthay thế! Nó hỗ trợ TẤT CẢ các tùy chọn. Màu được BẬT theo mặc định. Để tắt nó, chỉ cần sử dụng git diffc --no-colorhoặc git diffc --color=never. Xem man git diffđể biết chi tiết.

Vì tôi vừa hoàn thành git diffn(một công cụ để hiển thị git diffvới dòng 'n'umbers) tối qua, viết git diffclà chuyện nhỏ. Tôi nghĩ rằng tôi nên làm điều đó ngay bây giờ trong khi kiến ​​thức còn mới mẻ trong đầu.

Cài đặt git diffc:

Thực hiện theo các hướng dẫn ở cuối câu trả lời này tại đây , ngoại trừ mọi nơi bạn thấy git-diffntrong hướng dẫn, git-diffcthay vào đó hãy sử dụng . Điều đó bao gồm trong wgetlệnh quá. Tải xuống và cài đặt git diffcrất dễ dàng: đó chỉ là một vài lệnh.


0

Đây là một cách khác, đơn giản hơn để chỉ tìm các dòng đã được sửa đổi và do đó bắt đầu bằng một đầu ra duy nhất +hoặc -, trong khi vẫn giữ lại đầu ra màu:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. Câu -U0nói bao gồm 0 dòng ngữ cảnh xung quanh các dòng đã thay đổi - tức là: chỉ bao gồm chính các dòng đã thay đổi. Xem man git diff.
  2. Các -Echo grep cho phép nó làm việc với các biểu thức thông thường kéo dài
  3. Các $''cú pháp rõ ràng cho phép ANSI trích dẫn, mà đúng diễn giải ESC (escape, hoặc 0x1B) nhân vật đúng cách. Xem ở đây .
  4. Và đây là mô tả regex từ https://www.regex101.com :nhập mô tả hình ảnh ở đây
  5. Về cơ bản, ^khớp với phần đầu của dòng, \ekhớp với Escape char, là phần bắt đầu của mã màu trong thiết bị đầu cuối, \[khớp với char tiếp theo trong mã màu [, và sau đó (this|that)cú pháp khớp với "this" hoặc "that" , trong đó "this" là 32m+dòng + màu xanh lá cây và 31m-là dòng màu đỏ.
  6. Màu sắc là như thế này: \e[32mlà màu xanh lá cây và \e[31mlà màu đỏ.
  7. +hiển thị các dòng được đánh dấu bởi git diffnhư đã thêm, tất nhiên, và -hiển thị các dòng được đánh dấu git difflà đã xóa.
  8. Lưu ý rằng --color=neverđược yêu cầu trong grepbiểu thức thứ 2 để ngăn nó làm nổi bật các kết quả khớp của nó, điều này sẽ làm hỏng mã màu đi vào từ git diffbên trái.
  9. Các +đã được thoát quá như \+bởi vì nếu không +là một biểu thức chính quy (regex) ký tự đặc biệt trong đó xác định một hoặc nhiều lần xuất hiện của các yếu tố trước . Xem tại đây: https://en.wikipedia.org/wiki/Regular_expression#Basic_con accept .

Người giới thiệu:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. Trả lời bởi @ user650654: Git diff để chỉ hiển thị các dòng đã được sửa đổi
  3. Trả lời bởi @wisbucky: Git diff chỉ hiển thị các dòng đã được sửa đổi

Liên quan:

  1. [câu trả lời của riêng tôi] Git diff với số dòng (Nhật ký Git với số dòng)
  2. [câu trả lời của người khác] Git diff với số dòng (Nhật ký Git với số dòng)
  3. git diff với số dòng và căn chỉnh / thụt mã thích hợp
  4. git-filechange-search.sh- một kịch bản cho phép bạn tìm kiếm một tập tin cho một biến hoặc chức năng tên và con số ra cam kết chứa các thay đổi với điều đó biến hoặc chức năng tên. Ví dụ. cách sử dụng: ./git-filechange-search.sh path/to/my/file.cpp variable_namesẽ tìm thấy tất cả các cam kết với các thay đổi đối với file.cpp có variable_nametrong chúng. Điều này rất hữu ích để xem vị trí và thời điểm nhất định đã được thay đổi. Dường như đó là một tìm kiếm có thể quan sát các phần của tệp được hiển thị git blametheo thời gian.
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.