ฉันจะ“ ลบคอมไพล์” เส้นที่ถูกลบได้อย่างไร?


506

git blameดีมากสำหรับการแก้ไขและเพิ่มบรรทัด แต่ฉันจะหาได้อย่างไรเมื่อบรรทัดที่มีอยู่ในการคอมมิชชันก่อนหน้านี้ถูกลบในที่สุด ฉันกำลังคิดbisectแต่ฉันหวังว่าจะมีบางสิ่งที่ดีกว่า

(ก่อนที่คุณจะถาม: ในกรณีนี้ฉันเพิ่งทำgit log -pและค้นหารหัสบรรทัดและ (a) คนบ้าบางคนเพิ่งลบบรรทัดสำคัญในการส่งก่อนหน้าและ (b) ฉันเป็นคนงี่เง่านั้น)


4
มีการติดตามผลพร้อมคำตอบที่ชัดเจนว่าgit log -S<string> /path/to/fileต้องการ-cหรือ-ccแสดงการลบในระหว่างการรวม (ข้อขัดแย้ง)
cfi

3
มันควรจะเป็นและ-c --cc@ สิบสาม: ถูกต้องขอบคุณที่ชี้ให้เห็น! การกำกับดูแลที่โง่ หวังว่าฉันจะสามารถแก้ไขความคิดเห็น เพิ่มใหม่แล้วลบของฉันจากนั้นคุณลบของคุณเป็นงานที่ยุ่งยากเกินไปฉันเดา :)
cfi

4
ฉันหวังว่าgit blameจะมีตัวเลือกในการแสดงบรรทัดที่ถูกลบ (อาจมีขีดกลางหรือข้อความสีแดง) พร้อมการแก้ไขที่ถูกลบไป
Craig McQueen

มันจะยากที่จะเขียน? ฉันไม่รู้เกี่ยวกับ Git internals มากนัก
Malvolio

คำตอบ:


636

หากคุณรู้เนื้อหาของบรรทัดนี่เป็นกรณีที่ใช้ในอุดมคติสำหรับ:

git log -S <string> path/to/file

ซึ่งแสดงให้เห็นว่าคุณมุ่งมั่นที่จะแนะนำหรือลบตัวอย่างของสตริงนั้น นอกจากนี้ยัง-G<regex>มีสิ่งที่ทำสิ่งเดียวกันกับการแสดงออกปกติ! ดูman git-logและค้นหา-Gและ-Sตัวเลือกและหรือ pickaxe (ชื่อที่เป็นมิตรสำหรับคุณสมบัติเหล่านี้) สำหรับข้อมูลเพิ่มเติม

-Sตัวเลือกที่ถูกกล่าวถึงจริงในส่วนหัวของgit-blamemanpage git log -S...เกินไปในส่วนรายละเอียดที่มันให้ตัวอย่างการใช้


ยอดเยี่ยม ... สิ่งที่ฉันต้องการในการย้ายพอร์ตฉันกำลังทำงานกับ +1
jkp

37
หลังจากที่ใช้ Git สำหรับ 1+ ปีก็ยังคง amazes ฉันจะเห็นว่า Git เสมอมีที่ไหนสักแห่งคำสั่ง / ตัวเลือกที่จะอยู่เกือบทุกสถานการณ์การใช้งานที่ฉันมี ขอบคุณที่แบ่งปันสิ่งนี้มันเป็นสิ่งที่ฉันต้องการในตอนนี้!
Pascal Bourque

22
วิธีนี้ใช้ได้ผลกับฉันมาก่อน แต่ตอนนี้ฉันเห็นกรณีที่ไม่พบคำสั่งที่ลบบรรทัด ปรากฎว่าสายที่มีปัญหาถูกลบในการรวมการกระทำ - นั่นจะอธิบายถึงความล้มเหลวหรือไม่? ( git blame --reverseวิธีการพบว่า.)
antinome

9
@antinome หากต้องการแสดงการกระทำจากการรวมให้ใช้-cตัวเลือกเพิ่มเติม
yunzen

2
ฉันทำ ctrl + f ใน "-s" บน manpage และไม่พบอะไรเลย คุณเห็นหน้าที่ไหน ฉันใช้ git 1.8.5.2
temporary_user_name

134

ฉันคิดว่าสิ่งที่คุณต้องการคือ

git blame --reverse START..END filename

จากmanpage :

เดินไปข้างหน้าประวัติแทนที่จะถอยหลัง แทนที่จะแสดงการแก้ไขที่บรรทัดปรากฏขึ้นนี่แสดงการแก้ไขครั้งล่าสุดที่มีบรรทัดอยู่ สิ่งนี้ต้องมีการแก้ไขหลายอย่างเช่นเริ่มต้น .. สิ้นสุดที่มีเส้นทางไปสู่การตำหนิเมื่อเริ่มต้น

ด้วยgit blame reverseคุณสามารถค้นหาการคอมมิชชันล่าสุดที่ปรากฏในบรรทัดคุณยังต้องได้รับการคอมมิชชันที่มาหลังจากนั้น

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

git log --reverse --ancestry-path COMMIT^..master

14
หากมีการรวมหลายอย่างจากสาขาที่มีการเพิ่มบรรทัดลงในสาขาที่บรรทัดนั้นหายไป (หรือกรณีอื่น ๆ ที่มีหลายเส้นทางในสายเลือดตั้งแต่เริ่มต้นจนถึงสิ้นสุด) git blame --reverseจะแสดงการแก้ไขก่อนการรวมที่เรียงตามลำดับเวลา สุดท้ายไม่ใช่การแก้ไขก่อนการผสานเริ่มต้นที่การตัดสินใจไม่ได้เข้าแถว มีวิธีหาการแก้ไขที่เร็วที่สุดที่บรรทัดหยุดอยู่แทนที่จะเป็นรุ่นล่าสุดหรือไม่?
rakslice

2
@rakslice เพื่อให้คุณสามารถใช้ตำหนิ --reverse - first-parent ได้ดีกว่าเล็กน้อย
max630

17

เพียงทำคำตอบของ Cascabelให้สมบูรณ์:

git log --full-history -S <string> path/to/file

ฉันมีปัญหาแบบเดียวกับที่กล่าวถึงที่นี่แต่ปรากฎว่าเส้นขาดหายไปเนื่องจากการรวมความมุ่งมั่นจากสาขาได้เปลี่ยนกลับแล้วรวมกลับเข้าที่เดิมลบบรรทัดที่เป็นปัญหาได้อย่างมีประสิทธิภาพ --full-historyธงป้องกันการกระโดดข้ามกระทำเหล่านั้น


9

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

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

https://github.com/eantoranz/difflame


0

สำหรับการเปลี่ยนแปลงที่ซ่อนอยู่ในการรวมการกระทำ

การรวมกระทำกระทำโดยอัตโนมัติซ่อนการเปลี่ยนแปลงของพวกเขาจากเอาท์พุท Git ทั้งpickaxeและreverse-blameไม่พบการเปลี่ยนแปลง ดังนั้นบรรทัดที่ฉันต้องการได้รับการเพิ่มและลบออกในภายหลังและฉันต้องการที่จะหาผสานที่ลบมัน git log -p -- path/fileประวัติไฟล์แสดงให้เห็นว่ามันถูกเพิ่มเข้ามาเท่านั้น นี่คือวิธีที่ดีที่สุดที่ฉันค้นพบ:

git log -p -U9999 -- path/file

ค้นหาการเปลี่ยนแปลงจากนั้นค้นหาย้อนหลังสำหรับ "^ กระทำ" - "^ กระทำครั้งแรก" คือการกระทำที่ไฟล์สุดท้ายมีบรรทัดนั้น "^ commit" ที่สองคือหลังจากที่มันหายไป การมอบหมายครั้งที่สองอาจเป็นการลบออก -U9999จะหมายถึงการแสดงเนื้อหาไฟล์ทั้งหมด (หลังในแต่ละครั้งที่ไฟล์นั้นถูกเปลี่ยนแปลง) สมมติว่าไฟล์ของคุณที่มีอยู่ทั้งหมดสูงสุด 9999 เส้น

พบผสานเกี่ยวข้องใด ๆ ผ่านทางบังคับเดรัจฉาน (diff แต่ละผสานไปได้กระทำกับผู้ปกครองครั้งแรกทำงานกับตันกระทำ)

git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less

(ฉันพยายาม จำกัด ตัวกรองการแก้ไขเพิ่มเติม แต่ฉันพบปัญหาและไม่แนะนำสิ่งนี้การเปลี่ยนแปลงการเพิ่ม / การลบที่ฉันมองหาอยู่ในสาขาต่าง ๆ ซึ่งถูกรวมเข้าด้วยกันในเวลาที่ต่างกันและ A ... B ไม่รวม เมื่อการเปลี่ยนแปลงได้รวมเข้ากับการฉีดจริง)

แสดงแผนผัง Git ด้วยการกระทำทั้งสอง (และลบประวัติ Git ที่ซับซ้อนจำนวนมาก):

git log --graph --oneline A B ^$(git merge-base A B) (A คือการคอมมิชชันแรกข้างบน B คือการคอมมิทที่สองด้านบน)

แสดงประวัติของ A และประวัติของ B ลบประวัติของทั้ง A และ B

รุ่นอื่น (ดูเหมือนว่าจะแสดงเส้นทางเป็นเส้นตรงมากกว่าต้นไม้ประวัติ Git ปกติ - แต่ฉันชอบต้นไม้ประวัติศาสตร์ Git ปกติ):

git log --graph --oneline A...B

สามไม่ใช่สองจุด - สามจุดหมายถึง "r1 r2 - not $ (git merge-base - all r1 r2) เป็นชุดของการคอมมิทที่เข้าถึงได้จาก r1 (ด้านซ้าย) หรือ r2 (ขวา) ด้านข้าง) แต่ไม่ใช่จากทั้งคู่ " - แหล่งที่มา: "man gitrevisions"

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