Git diff เพื่อแสดงเฉพาะบรรทัดที่ได้รับการแก้ไข


129

เมื่อฉันทำ git diff จะแสดงบรรทัดที่เพิ่มเข้ามา:

+ this line is added

บรรทัดที่ถูกลบ:

- this line is removed

แต่ยังแสดงหลายบรรทัดที่ไม่ได้แก้ไข:

this line is not modified
this line is also not modified

สิ่งนี้ส่งผลให้ git ที่แท้จริงแตกต่างกันดังนี้:

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

ฉันขอให้ git แสดงเฉพาะบรรทัดที่ได้รับการแก้ไขและละเว้นโค้ดอื่น ๆ ที่ยังไม่ได้แก้ไขได้หรือไม่? ฉันได้เขียนวิธีการที่จะลบบรรทัดทั้งหมดที่ไม่มีเครื่องหมาย "+" หรือ "-" อยู่ข้างหน้า แต่ฉันแน่ใจว่าต้องมีวิธีที่ง่ายกว่านี้

ใน git diff ของฉันฉันสนใจแค่ดูบรรทัดที่ถูกแก้ไข

ขอบคุณล่วงหน้า.

คำตอบ:


183

สิ่งที่คุณต้องการคือความแตกต่างที่มีบริบท 0 บรรทัด คุณสามารถสร้างสิ่งนี้ได้ด้วย:

git diff --unified=0

หรือ

git diff -U0

คุณยังสามารถตั้งค่านี้เป็นตัวเลือกการกำหนดค่าสำหรับที่เก็บนั้น:

git config diff.context 0

หากต้องการตั้งค่าทั่วโลกสำหรับที่เก็บใด ๆ :

 git config --global diff.context 0

4
ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว วิธีนี้แก้ปัญหาได้ครึ่งหนึ่ง แต่ฉันยังได้รับบางบรรทัดเช่น "@@ -1 +1 @@" ใน diff และด้านบนของ git diff มี "diff --git a / db / xxxxxxx b / db / xxxx index xxxxx..aaaaaaa bbbbbbbb
r3b00t

3
ฉันไม่คิดว่า git จะมีวิธีใดในการหลีกเลี่ยงการแสดงบรรทัดเหล่านั้นเพราะความแตกต่างจะไม่สมเหตุสมผลหากไม่มีพวกเขา (คุณไม่สามารถรู้ได้ว่าคุณกำลังดูไฟล์ใดอยู่หรืออยู่ที่ไหนในไฟล์)
Chris Hayes

8
@Rakesh: ในการขยาย git-diff จะพยายามสร้างความแตกต่างที่สามารถใช้เป็นแพตช์ไปยังไฟล์ต้นทางได้จริงซึ่งเป็นไปไม่ได้หากไม่มีข้อมูลนั้น git diff | egrep "^(\+|-) "วิธีเดียวที่จะลบมันจะโพสต์กระบวนการมันเองเช่นผ่านทาง
Chris Hayes

1
git config --global diff.context 0 ที่จะมีขึ้นทั่วโลก
Andrzej Rehmann

หากคุณต้องการเห็นในไดเร็กทอรีเฉพาะให้ลอง git diff -U0 <dir>
Eswar Yaganti

42

แฮ็กอื่น (บน un * x) เพื่อแสดงเฉพาะบรรทัดที่ขึ้นต้นด้วย+และ-:

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

โค้ดด้านบนทำสิ่งต่อไปนี้:

  • git diff -U0: เลือก 0 บรรทัดบริบท
  • grep แรกรวมเฉพาะบรรทัดทั้งหมดที่ขึ้นต้นด้วย+หรือ-
  • grep ที่สองไม่รวมบรรทัดที่ขึ้นต้นด้วย--- a/หรือ+++ b/

สี

หากต้องการแสดงความแตกต่างของสีให้ลองทำดังต่อไปนี้:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • นิพจน์^\e\[[^m]*m[-+]มองหาจุดเริ่มต้นของบรรทัด ( ^) จากนั้นอักขระ Escape ( \e) ตามด้วย[ซึ่งเริ่มต้นลำดับการหลบหนีจากนั้นอักขระใด ๆ ที่ไม่ใช่ "m" (ตัวเลขอัฒภาคหรือไม่มีอะไรเลย) ตามด้วย " m "ซึ่งสิ้นสุดลำดับการหลบหนี
  • โปรดทราบว่าทั้งหมดต่อไปนี้เป็นลำดับการหลีกเลี่ยงที่ถูกต้อง: \e[0m(รีเซ็ต), \e[m(รีเซ็ตด้วย), \e[1m(ตัวหนาบน), \e[31m(สีแดง), \e[32m(สีเขียว), \e[9;31m(ขีดฆ่า + สีแดง), \e[31;9m(สีแดง + ขีดฆ่า), \e[1;4;9;31m(ตัวหนา + ขีดเส้นใต้ + ขีดฆ่า + แดง) สีคอมไพล์เริ่มต้นใช้สีแดงและสีเขียว แต่สามารถกำหนดค่าใหม่ได้
  • --colorเหมือนกับ--color=always.
  • ข้อ จำกัด ใน--- a/หรือที่+++ b/จะปรากฏที่จุดเริ่มต้นของบรรทัดถูกลบออกเพื่อรองรับสำหรับลำดับการหลีกเลี่ยงและอาจนำไปสู่กรณีขอบ

หมายเหตุเพิ่มเติม:

  • การแก้ปัญหาดังกล่าวข้างต้นจะต้องแก้ไขหากคุณใช้ตัวเลือกคอมไพล์ diff เพิ่มเติมเช่น-R, --src-prefix, --dst-prefix, --no-prefixฯลฯ
  • ทั้งสอง grep สามารถรวมกันเป็นตัวเดียวgrep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )'ได้ แต่ฉันพบว่าเวอร์ชัน grep คู่นั้นเข้าใจง่ายกว่า

2
ทำได้ดีนี่. โหวตให้คำอธิบายที่ชัดเจนในแต่ละตัวกรอง
henrebotha

ฉันเห็นมากของgit diff"หัว" บรรทัดชนิดซึ่งเริ่มต้นด้วย@@แต่สิ่งที่เป็นgit diffเส้นที่เริ่มต้นด้วย---หรือ+++? ฉันไม่รู้จักคนเหล่านั้น
Gabriel Staples

อ่าไม่เป็นไร สิ่งเหล่านี้แสดงถึงชื่อไฟล์สำหรับไฟล์ที่มีการเพิ่ม ( +++) หรือการลบ ( ---) ผมเห็นว่าที่นี่ตอนนี้: git-scm.com/docs/git-diff#_combined_diff_format
Gabriel Staples

การแก้ไขอีกครั้ง: --- a/filenameดูเหมือนว่าจะแสดงถึง "ไฟล์ทางด้านซ้าย" หรือไฟล์เหมือนเดิมและ+++ b/filenameดูเหมือนว่าจะแสดงถึง "ไฟล์ทางด้านขวา" หรือไฟล์ที่ตอนนี้มีการเปลี่ยนแปลงของคุณ ฉันคุ้นเคยกับการใช้git difftoolmeldมากซึ่งแสดงการเปรียบเทียบแบบเคียงข้างกันที่สวยงามซึ่งฉันไม่เคยคุ้นเคยกับการมองมาgit diffก่อนดังนั้นมันก็ยังดูแปลกสำหรับฉันและฉันไม่เคยมองความแตกต่างเหล่านี้มาก่อน
Gabriel Staples

1
@GabrielStaples เพิ่มการรองรับสีแล้ว ขอบคุณ
user650654

6

ติดตามความคิดเห็นล่าสุดของคริสที่เป็นปัญหาหลักที่มีการโพสต์คือการที่คุณต้องการที่จะให้สายที่เริ่มต้นด้วยแต่คุณยังต้องการที่จะกรองจากผู้ที่เริ่มต้นด้วย-|+ ---|+++หากคุณกำลังจัดเก็บไฟล์แพตช์ใน repo ของคุณ (ฉันทำในPydoop ) ในทางกลับกันคุณต้องการให้บรรทัดที่ขึ้นต้นด้วย--|++ดังนั้น regexp จึงมีส่วนเกี่ยวข้องเล็กน้อย:

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

regexp ใช้การมองในแง่ลบ: ดูคำตอบของ Peter Boughton สำหรับคำถามนี้สำหรับคำอธิบายโดยละเอียด

หากคุณทำสิ่งนี้บ่อยๆคุณอาจต้องการตั้งค่าชื่อแทน git สำหรับมัน:

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

1
สิ่งนี้ไม่ได้ผลสำหรับฉันใน Windows git bash ไม่รู้ว่าทำไม (grep บอกว่าตัวเลือก P ไม่ถูกต้อง) ไม่มี chutzpah ที่จะตรวจสอบในขณะนี้
Dennis

1
-Pหรือ--perl-regexpใช้ในการตีความรูปแบบเป็นนิพจน์ทั่วไปของ Perl แต่ไม่ได้นำไปใช้เสมอไป มันไม่ได้ผลสำหรับฉันบน OSX gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega

5

ฉันคิดว่าสำหรับกรณีง่ายๆ regex อาจสั้นลงและจำได้ง่ายขึ้นมากโดยมีข้อแม้ว่าจะไม่ได้ผลหากคุณมีการเปลี่ยนแปลงบรรทัดโดยที่บรรทัดนั้นเริ่มต้นด้วย+หรือ-

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

regex บอกว่าบรรทัดควรขึ้นต้นด้วย+หรือ-และอักขระต่อไปนี้ไม่ควรเป็นตัวอักษรทั้งสองตัว ฉันได้ผลลัพธ์เหมือนกันไม่ว่าฉันจะหนีจาก+ที่นี่หรือไม่ ...


ตัวอย่าง:

$ cat testfile
A
B
C
D
E
F
G

บอกว่าผมเปลี่ยนแปลงCไปX, EไปYและจะGZ

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

อย่างที่ฉันได้กล่าวไว้ข้างต้นนี่เป็นเพียงสำหรับกรณีส่วนใหญ่ หากคุณไปป์เอาต์พุตนั้นไปยังไฟล์doutแล้วลอง regex เดียวกันก็จะไม่ได้ผล

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

อย่างไรก็ตามหวังว่าจะช่วยในกรณีของคุณ


สำหรับกรณีที่บรรทัดขึ้นต้นด้วย "-" จะใช้ไม่ได้ ตัวอย่าง: - name: No pdbในไฟล์ yaml
anapaulagomes

3

คำตอบนี้จะคงไว้ซึ่งสีแดง / เขียวดั้งเดิมเพื่อให้อ่านง่าย ฉันให้รูปแบบไวยากรณ์บางประการ:

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'

คำอธิบาย:

  • git diff --colorเป็นสิ่งจำเป็นเพื่อป้องกันการคอมไพล์จากการปิดใช้งานสีเมื่อมันเป็นท่อ
  • grep --color=neverเพื่อป้องกันไม่ให้ grep ลบสีเดิมและเน้นสตริงจับคู่
  • เรากำลังจับคู่สำหรับบรรทัดที่ขึ้นต้นด้วยรหัสหนีสีแดง ( \e[31m) หรือสีเขียว ( \e[32m)
  • $'...'(ANSI-C ไวยากรณ์ quoting) หรือ-P(Perl ไวยากรณ์) คือการปล่อยให้grepการตีความ\eหรือ\033เป็นESCตัวอักษร

ขอบคุณสำหรับสิ่งนี้. นี่เป็นรูปแบบทางเลือกที่ฉันเพิ่งสร้างขึ้น $''ส่วนของคุณช่วยฉันโดยเฉพาะ stackoverflow.com/a/61929887/4561887
Gabriel Staples

1

วิธีการใช้งานawkที่จะแสดงเพียง+และ-สายบัญชีสำหรับสีหรือข้อความใด ๆ ที่จัดรูปแบบgit diffอาจจะมีการแสดงผล:

ไม่ใช่หนึ่งในคำตอบอื่น ๆ ที่นี่ (รวมถึงคำตอบอื่น ๆ ของฉัน ) จะทำสิ่งที่คุณต้องการได้อย่างถูกต้อง 100% อย่างไรก็ตามคำตอบนี้จะ นี่คือ 1 ซับที่คุณสามารถคัดลอกและวางลงในเทอร์มินัลของคุณได้ ฉันเพิ่งสร้างมันขึ้นมาหลายบรรทัดเพื่อให้อ่านง่าย - คุณสามารถคัดลอกและวางแบบเดียวกันไม่ว่าจะด้วยวิธีใดก็ได้ดังนั้นฉันจึงอาจทำให้อ่านได้! มันขึ้นอยู่กับawkภาษาโปรแกรม:

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

นี่คือคุณสมบัติของมัน เมื่อนำคุณสมบัติเหล่านี้มารวมกันจะช่วยแก้ไขข้อบกพร่องของคำตอบอื่น ๆ ทั้งหมดได้ที่นี่:

  1. จัดการกับเอาต์พุตสีและไม่มีสี นั่นคือสิ่งที่นิพจน์ทั่วไปทำ:^(\033\[(([0-9]{1,2};?){1,10})m)?
  2. สามารถจัดการกับทุกสีและทุกรูปแบบข้อความ OPTIONS รวมทั้งตัวหนาตัวเอียงขีด ฯลฯ ซึ่งคุณสามารถตั้งค่าของคุณในgit configการตั้งค่า นั่นเป็นเหตุผลที่ regex ด้านบนมี;?และ{1,10}อยู่ในนั้น: หากตรวจพบจุดเริ่มต้นของรหัสการจัดรูปแบบสีหรือข้อความจะจับคู่รหัส ANSI รวมกันได้สูงสุด 10 ลำดับ
  3. มันไม่ ได้แก่ สายที่เริ่มต้นด้วย@@และคำว่าdiffเป็นคำตอบที่ได้รับการยอมรับไม่ หากคุณต้องการบรรทัดเหล่านั้น (ซึ่งตรงไปตรงมาฉันคิดว่ามีประโยชน์ :)) ให้ทำสิ่งนี้แทน:

    git diff --unified=0
    

    หรือ

    git diff -U0
    
  4. มันแสดงผลลัพธ์ในลักษณะเดียวกับที่ทำgit diff: ในlessเพจเจอร์ที่มีเอาต์พุตสีเสริม ( -R) และเฉพาะในกรณีที่ข้อความเป็น> 1 เพจ ( -F) และในขณะที่รักษาหน้าปัจจุบันของข้อความบนหน้าจอเมื่อคุณquit ( -X) .

นอกจากนี้ยังมีประโยชน์ในการมีประสิทธิภาพและกำหนดค่าได้ง่ายเนื่องจากใช้ภาษาโปรแกรม awk

หากคุณสนใจที่จะเรียนรู้awkนี่คือแหล่งข้อมูลบางส่วน:

  1. gawk(GNU awk) คู่มือ: https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. ศึกษาgit diffnและแสดงความคิดเห็นในนั้น: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. หากคุณต้องการgit diffnเช่นกันซึ่งgit diffมีหมายเลขบรรทัดโปรดดูที่นี่: Git diff กับหมายเลขบรรทัด (บันทึก Git พร้อมหมายเลขบรรทัด)
  3. "สวัสดีชาวโลก" และตัวอย่างการทดสอบไวยากรณ์บางส่วน: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

เพื่อเป็นโบนัสฉันได้รวบรวมข้อมูลข้างต้นเพื่อใช้เป็นgit diffcซึ่งหมายความว่า "คอมไพล์ที่แตกต่างเพื่อแสดงเฉพาะ 'c'hanges" การใช้งานที่เหมือนกันไปgit diff; แค่ใช้git diffcแทน! รองรับตัวเลือกทั้งหมด สีจะเปิดตามค่าเริ่มต้น ที่จะปิดเพียงแค่ใช้หรือgit diffc --no-color git diffc --color=neverดูman git diffรายละเอียด

เนื่องจากฉันเพิ่งทำเสร็จgit diffn(เครื่องมือที่แสดงgit diffด้วยบรรทัด 'n'umbers) เมื่อคืนนี้การเขียนgit diffcเป็นเรื่องเล็กน้อย ฉันคิดว่าฉันทำได้ดีกว่าตอนนี้ในขณะที่ความรู้ยังคงอยู่ในหัวของฉัน

ติดตั้งgit diffc:

ปฏิบัติตามคำแนะนำท้ายคำตอบที่นี่ยกเว้นทุกที่ที่คุณเห็นgit-diffnในคำแนะนำให้ใช้git-diffcแทน ซึ่งรวมอยู่ในwgetคำสั่งด้วย การดาวน์โหลดและติดตั้งgit diffcทำได้ง่ายเพียงไม่กี่คำสั่ง


0

นี่เป็นอีกวิธีที่ง่ายกว่าในการค้นหาเฉพาะเส้นที่ได้รับการแก้ไขและด้วยเหตุนี้จึงเริ่มต้นด้วยเส้นเดียว+หรือ-ในขณะที่ยังคงเอาท์พุทสีไว้:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. คำ-U0กล่าวที่จะรวม 0 บรรทัดของบริบทรอบ ๆ บรรทัดที่เปลี่ยนแปลงนั่นคือ: รวมเฉพาะบรรทัดที่เปลี่ยนแปลงเอง ดูman git diff.
  2. -Eสำหรับ grep ช่วยให้การทำงานมีการแสดงออกปกติขยาย
  3. $''ไวยากรณ์ที่เห็นได้ชัดช่วยให้ ANSI quoting ซึ่งถูกตีความ ESC (หลบหนีหรือ 0x1b) ตัวละครที่ถูกต้อง ดูที่นี่ .
  4. และนี่คือคำอธิบาย regex จากhttps://www.regex101.com :ใส่คำอธิบายภาพที่นี่
  5. โดยทั่วไปจะ^จับคู่จุดเริ่มต้นของบรรทัด\eตรงกับอักขระ Escape ซึ่งเป็นจุดเริ่มต้นของรหัสสีในเทอร์มินัล\[ตรงกับอักขระถัดไปในรหัสสีนั่นคือ[จากนั้น(this|that)ไวยากรณ์จะตรงกับ "this" หรือ "that" โดยที่ "นี่" คือ32m+เส้น + สีเขียวและ31m-เป็นเส้นสีแดง
  6. สีจะเป็นแบบนี้\e[32mคือเขียวและ\e[31mแดง
  7. +แสดงบรรทัดที่ทำเครื่องหมายgit diffว่าเพิ่มแล้วและ-แสดงบรรทัดที่ทำเครื่องหมายgit diffว่าถูกลบ
  8. โปรดทราบว่า--color=neverถูกต้องในครั้งที่ 2 grepการแสดงออกในการสั่งซื้อเพื่อป้องกันไม่ให้ไฮไลต์การแข่งขันของตนซึ่งจะกรูขึ้นรหัสสีมาจากgit diffทางด้านซ้าย
  9. +จะต้องมีการหลบหนีก็เป็น\+เพราะมิฉะนั้น+คือการแสดงออกปกติ (regex) อักขระพิเศษซึ่งระบุหนึ่งหรือมากกว่าการเกิดขึ้นขององค์ประกอบที่ก่อนหน้านี้ ดูที่นี่: https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts

อ้างอิง:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. ตอบโดย @ user650654: Git diff เพื่อแสดงเฉพาะบรรทัดที่ถูกแก้ไข
  3. ตอบโดย @wisbucky: Git diff เพื่อแสดงเฉพาะบรรทัดที่แก้ไขแล้ว

ที่เกี่ยวข้อง:

  1. [คำตอบของฉันเอง] Git ต่างกับหมายเลขบรรทัด (บันทึก Git พร้อมหมายเลขบรรทัด)
  2. [คำตอบของคนอื่น] Git ต่างกับหมายเลขบรรทัด (บันทึก Git พร้อมหมายเลขบรรทัด)
  3. git แตกต่างกับหมายเลขบรรทัดและการจัดตำแหน่ง / การเยื้องรหัสที่เหมาะสม
  4. git-filechange-search.sh- สคริปต์ที่ช่วยให้คุณค้นหาไฟล์สำหรับตัวแปรหรือชื่อฟังก์ชันและค้นหาว่าคอมมิตใดที่มีการเปลี่ยนแปลงกับตัวแปรหรือชื่อฟังก์ชันนั้น อดีต การใช้งาน: ./git-filechange-search.sh path/to/my/file.cpp variable_nameจะพบการกระทำทั้งหมดที่มีการเปลี่ยนแปลง file.cpp ที่มีvariable_nameอยู่ในนั้น สิ่งนี้มีประโยชน์ในการดูว่าคุณลักษณะบางอย่างมีการเปลี่ยนแปลงที่ไหนและเมื่อใด ราวกับว่าเป็นการค้นหาที่สามารถสังเกตเห็นส่วนต่างๆของไฟล์ที่แสดงgit blameเมื่อเวลาผ่านไป
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.