ดึงบันทึกการกระทำสำหรับบรรทัดที่ระบุในไฟล์หรือไม่?


503

มีวิธีใดที่จะได้รับคอมไพล์เพื่อมอบบันทึกการกระทำให้กับคุณแค่คอมมิทที่แตะบรรทัดหนึ่งในไฟล์หรือไม่?

กดไลค์git blameแต่git blameจะแสดงให้คุณเห็น LAST ที่ส่งไปถึงบรรทัดนั้น

ฉันต้องการบันทึกที่คล้ายกันไม่ใช่รายการของการผูกมัดที่ใดก็ได้ในไฟล์ แต่เพียงการคอมมิทที่แตะบรรทัดใดบรรทัดหนึ่ง


2
ดูเพิ่มเติมที่: Git
blues

คำตอบ:


631

ดูเพิ่มเติมGit: ค้นพบที่ commits เคยสัมผัสช่วงของเส้น


ตั้งแต่ Git 1.8.4 , git logมี-Lเพื่อดูวิวัฒนาการของช่วงของสายที่

ตัวอย่างเช่นสมมติว่าคุณดูgit blameเอาต์พุตของ นี่-L 150,+11หมายถึง "ดูเฉพาะบรรทัดที่ 150 ถึง 150 + 11":

$ git blame -L 150,+11 -- git-web--browse.sh
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 150)            die "The browser $browser is not
a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 151)    fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 152) fi
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 153) 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 154) case "$browser" in
81f42f11 git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:38 +0100 155) firefox|iceweasel|seamonkey|iceape)
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 156)    # Check version because firefox < 2.0 do
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 157)    vers=$(expr "$($browser_path -version)" 
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 158)    NEWTAB='-new-tab'
5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 159)    test "$vers" -lt 2 && NEWTAB=''
a0685a4f git-web--browse.sh (Dmitry Potapov   2008-02-09 23:22:22 -0800 160)    "$browser_path" $NEWTAB "$@" &

และคุณอยากรู้ประวัติของสิ่งที่เป็นเส้น 155

git logจากนั้นใช้ ที่นี่-L 155,155:git-web--browse.shหมายถึง "ติดตามวิวัฒนาการของบรรทัดที่ 155 ถึง 155 ในไฟล์ชื่อgit-web--browse.sh"

$ git log --pretty=short -u -L 155,155:git-web--browse.sh
commit 81f42f11496b9117273939c98d270af273c8a463
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: support opera, seamonkey and elinks

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -143,1 +143,1 @@
-firefox|iceweasel)
+firefox|iceweasel|seamonkey|iceape)

commit a180055a47c6793eaaba6289f623cff32644215b
Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

    web--browse: coding style

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -142,1 +142,1 @@
-    firefox|iceweasel)
+firefox|iceweasel)

commit 5884f1fe96b33d9666a78e660042b1e3e5f9f4d9
Author: Christian Couder <chriscool@tuxfamily.org>

    Rename 'git-help--browse.sh' to 'git-web--browse.sh'.

diff --git a/git-web--browse.sh b/git-web--browse.sh
--- /dev/null
+++ b/git-web--browse.sh
@@ -0,0 +127,1 @@
+    firefox|iceweasel)

2
'git log --topo-order --graph -u -L 155,155: git-web--browse.sh' - ทำให้เกิดข้อผิดพลาดร้ายแรง: 'ชื่อวัตถุที่ไม่ถูกต้อง 155,155' รุ่น Git: 1.8.3.2 ข้อเสนอแนะใด ๆ
BairDev

12
อัปเกรดเป็น Git 1.8.4 หรือใหม่กว่า
Matt McClure

4
ถ้าฉันต้องการรู้ว่า "ประวัติศาสตร์ของสิ่งที่เป็นสาย 155 ในการกระทำ" (แทนที่จะเป็นบรรทัดที่ 155 ในหัว) ฉันสามารถใช้งานได้git log commitA-hash -L 155,155:file-nameหรือไม่?
Ida

@ บางอย่างฉันไม่ได้มีความต้องการที่แข็งแกร่ง
Matt McClure

มันทำงานได้ดียกเว้นว่าไฟล์ถูกย้าย / เปลี่ยนชื่อ ... ดูเหมือนว่า - follow ไม่ชอบที่จะถูกรวมกับ args ช่วงของบรรทัด
Mike Ellery

66

คุณสามารถได้รับชุดของการกระทำโดยใช้ขวาน

git log -S'the line from your file' -- path/to/your/file.txt

สิ่งนี้จะให้ความมุ่งมั่นทั้งหมดที่มีผลกับข้อความนั้นในไฟล์นั้น หากไฟล์ถูกเปลี่ยนชื่อในบางจุดคุณสามารถเพิ่ม --follow-parent

หากคุณต้องการตรวจสอบความมุ่งมั่นของแต่ละการแก้ไขคุณสามารถส่งผลให้แสดงคอมไพล์:

git log ... | xargs -n 1 git show

5
ฉันไม่แน่ใจว่าฉันเห็นว่ามันช่วยได้อย่างไร หากข้อความได้รับผลกระทบบรรทัดนั้นจะไม่เหมือนเดิมอีกต่อไปดังนั้น pickaxe จะแสดงเฉพาะการเปลี่ยนแปลงล่าสุดของคุณ จากนั้นคุณจะต้องทำgit log -S'the previous version of the line'และอื่น ๆ git blame -Lเหมือนกับคุณต้องการสิ้นสุดการทำด้วย และมันจะช้ากว่าgit blameนี้เนื่องจากมันจะต้องค้นหาข้อความทุกที่ไม่ใช่แค่ในที่ที่กำหนด
Cascabel

คุณสามารถใช้ regex ในนั้นเพื่อให้ยอมรับมากขึ้น ขณะนี้ยังไม่มีวิธี "ย้อนเวลาผ่านแพตช์" ย้อนเวลาโดยไม่ต้องมีสคริปต์ที่ซับซ้อน ฉันหวังว่า gitk จะรับฟังก์ชั่นนี้ในมุมมองแพตช์ในอนาคต
Adam Dymitruk

3
ทำไมนี้เรียกว่ารับส่งขวาน ? :)
Ciprian Tomoiagă

43

ลองใช้คำสั่งด้านล่างที่ใช้ใน Git 1.8.4

git log -u -L <upperLimit>,<lowerLimit>:<path_to_filename>

ดังนั้นในกรณีของคุณupperLimit& lowerLimitคือการสัมผัสline_number

ข้อมูลเพิ่มเติม - https://www.techpurohit.com/list-some-useful-git-commands


2
ผมคิดว่าจะถูกละเว้นเมื่อใช้--pretty=short -Lโปรดแก้ไข
Vic Seedoubleyew

14

วิธีที่ง่ายมากที่จะทำเช่นนี้คือการใช้เสียงเรียก-ผู้ลี้ภัย เพียงแค่เปิดไฟล์เป็นกลุ่มเลือกบรรทัดที่คุณสนใจVแล้วใช้

:Glog

ตอนนี้คุณสามารถใช้:cnextและ:cprevดูการแก้ไขทั้งหมดของไฟล์ที่มีการแก้ไขบรรทัดนั้น ป้อนข้อมูล:Gblameเพื่อดู sha, ผู้แต่งและข้อมูลวันที่


13

ลดความซับซ้อนของคำตอบ @ matt -

git blame -L14,15 -- <file_path>

14 to 15ที่นี่คุณจะได้รับโทษสำหรับสายที่

เนื่องจาก-Lตัวเลือกที่คาดว่าRangeเป็นพารามิเตอร์ที่เราไม่สามารถได้รับBlameสำหรับบรรทัดเดียวใช้-L option`

การอ้างอิง


10

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

ถ้าคุณโชคดีพอที่กำลังว่าเส้นมักจะมีบางgit blame -Lลักษณะการระบุเช่นการกำหนดให้กับตัวแปรที่มีชื่อไม่เคยเปลี่ยนคุณสามารถใช้เป็นทางเลือกสำหรับ regex ตัวอย่างเช่น:

git blame -L '/variable_name *= */',+1

แต่นี่เป็นเพียงการจับคู่แรกสำหรับ regex นั้นดังนั้นหากคุณไม่มีวิธีที่ดีในการจับคู่สายมันไม่ได้มีประโยชน์มากนัก

คุณสามารถแฮ็คบางอย่างได้ฉันคิดว่า ตอนนี้ฉันไม่มีเวลาเขียนโค้ด แต่ ... มีบางอย่างในบรรทัดเหล่านี้ git blame -n -L $n,$n $fileวิ่ง สนามแรกคือก่อนหน้านี้กระทำสัมผัสและฟิลด์ที่สองเป็นจำนวนเส้นในที่กระทำเพราะมันอาจจะมีการเปลี่ยนแปลง คว้าสิ่งเหล่านั้นและเรียกใช้git blame -n $n,$n $commit^ $fileนั่นคือสิ่งเดียวกันเริ่มต้นจากการคอมมิทก่อนที่ไฟล์จะถูกเปลี่ยน

(โปรดทราบว่าสิ่งนี้จะทำให้คุณล้มเหลวหากการส่งครั้งล่าสุดที่เปลี่ยนสายเป็นการรวมการส่งมอบวิธีหลักอาจเกิดขึ้นได้หากการเปลี่ยนแปลงรายการเป็นส่วนหนึ่งของการแก้ไขข้อขัดแย้งในการรวม)

แก้ไข: ฉันเกิดขึ้นกับโพสต์รายการจดหมายนี้ตั้งแต่เดือนมีนาคม 2011 วันนี้ซึ่งกล่าวถึงtigและgit guiมีคุณสมบัติที่จะช่วยคุณทำสิ่งนี้ ดูเหมือนว่าคุณสมบัติจะได้รับการพิจารณา แต่ยังไม่เสร็จสิ้นสำหรับคอมไพล์เอง


6

สิ่งนี้จะเรียกร้องgit blameให้ทุกการแก้ไขที่มีความหมายแสดงบรรทัด$LINEของไฟล์$FILE:

git log --format=format:%H $FILE | xargs -L 1 git blame $FILE -L $LINE,$LINE

ตามปกติตำหนิจะแสดงหมายเลขการแก้ไขในตอนต้นของแต่ละบรรทัด คุณสามารถต่อท้าย

| sort | uniq -c

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


อีกครั้งฉันคิดว่ามันใช้งานไม่ได้เพราะมันไม่ได้ติดตามตำแหน่งก่อนหน้าของบรรทัดนั้น ดังนั้นหากมีการเพิ่มสาย 2 คอมมิชชันที่ผ่านมาคุณจะมองไปที่บรรทัดอื่น
Vic Seedoubleyew

6

นี่เป็นวิธีแก้ปัญหาที่กำหนดนามแฝง git ดังนั้นคุณจะสามารถใช้มันได้

git rblame -M -n -L '/REGEX/,+1' FILE

ตัวอย่างผลลัพธ์:

00000000 18 (Not Committed Yet 2013-08-19 13:04:52 +0000 728) fooREGEXbar
15227b97 18 (User1 2013-07-11 18:51:26 +0000 728) fooREGEX
1748695d 23 (User2 2013-03-19 21:09:09 +0000 741) REGEXbar

คุณสามารถกำหนดนามแฝงใน. gitconfigของคุณหรือเพียงแค่เรียกใช้คำสั่งต่อไปนี้

git config alias.rblame !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); echo $line; done' dumb_param

นี่คือหนึ่งซับน่าเกลียดดังนั้นนี่คือฟังก์ชั่นทุบตีเทียบเท่า de-obfuscated:

git-rblame () {
    local commit line
    while line=$(git blame "$@" $commit 2>/dev/null); do
        commit="${line:0:8}^"
        if [ "00000000^" == "$commit" ]; then
            commit=$(git rev-parse HEAD)
        fi
        echo $line
    done
}

โซลูชัน pickaxe ( บันทึก git --pickaxe-regex -S'REGEX ' ) จะให้เฉพาะการเพิ่ม / ลบบรรทัดเท่านั้นไม่ใช่การแก้ไขอื่น ๆ ของบรรทัดที่มีนิพจน์ทั่วไป

ข้อ จำกัด ของการแก้ปัญหานี้คือการตำหนิ gitส่งคืนการจับคู่ที่ 1 ของ REGEX เท่านั้นดังนั้นหากมีการแข่งขันหลายรายการการเรียกซ้ำอาจ "กระโดด" เพื่อไปตามเส้นทางอื่น อย่าลืมตรวจสอบผลลัพธ์ประวัติเต็มรูปแบบเพื่อหา "การกระโดด" เหล่านั้นแล้วแก้ไข REGEX ของคุณเพื่อเพิกเฉยต่อเส้นกาฝาก

สุดท้ายนี่คือเวอร์ชั่นอื่นที่รันgit showในแต่ละคอมมิทเพื่อรับส่วนต่างที่สมบูรณ์:

git config alias.rblameshow !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); git show $commit; done' dumb_param

2

คุณสามารถผสมgit blameและgit logคำสั่งเพื่อดึงข้อมูลสรุปของแต่ละการคอมมิตในคำสั่ง git blame และผนวกเข้าด้วยกัน คล้ายกับสคริปต์ทุบตี + awk ต่อไปนี้ มันต่อท้ายสรุปการกระทำเป็นความคิดเห็นรหัสแบบอินไลน์

git blame FILE_NAME | awk -F" " \
'{
   commit = substr($0, 0, 8);
   if (!a[commit]) {
     query = "git log --oneline -n 1 " commit " --";
     (query | getline a[commit]);
   }
   print $0 "  // " substr(a[commit], 9);
 }'

ในหนึ่งบรรทัด:

git blame FILE_NAME | awk -F" " '{ commit = substr($0, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print $0 "  // " substr(a[commit], 9); }'

2

ในกรณีของฉันหมายเลขบรรทัดมีการเปลี่ยนแปลงมากเมื่อเวลาผ่านไป ฉันยังใช้ git 1.8.3 ซึ่งไม่รองรับ regex ใน "git blame -L" (RHEL7 ยังคงมี 1.8.3)

myfile=haproxy.cfg
git rev-list HEAD -- $myfile | while read i
do
    git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"
done | grep "<sometext>"

หนึ่งในสายการบิน:

myfile=<myfile> ; git rev-list HEAD -- $myfile | while read i; do     git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"; done | grep "<sometext>"

แน่นอนว่าสิ่งนี้สามารถทำเป็นสคริปต์หรือฟังก์ชั่นได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.