วิธีค้นหา Git และ Mercurial ทั้งหมดที่คอมมิตในที่เก็บเพื่อหาสตริงที่แน่นอน?


287

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

ฉันรู้วิธีรับบันทึกการกระทำทั้งหมดในประวัติศาสตร์ แต่สิ่งเหล่านี้ไม่รวมถึงกิ่งไม้หรือ blob dangling เพียงประวัติของ HEAD ฉันต้องการให้พวกเขาทั้งหมดเพื่อค้นหาความมุ่งมั่นที่ผิดพลาด

ฉันต้องการทราบวิธีการทำเช่นนี้ใน Mercurial เนื่องจากฉันกำลังพิจารณาสวิตช์


ที่เกี่ยวข้อง: วิธีการ grep คอมไพล์สำหรับคำที่แน่นอน

คำตอบ:


331

git log -gท่านสามารถเข้าดูห้อยกระทำด้วย

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

ดังนั้นคุณสามารถทำเช่นนี้เพื่อค้นหาสตริงเฉพาะในข้อความกระทำที่เป็นอันตราย:

git log -g --grep=search_for_this

อีกทางเลือกหนึ่งถ้าคุณต้องการค้นหาการเปลี่ยนแปลงของสตริงคุณสามารถใช้ตัวเลือกการค้นหา pickaxe "-S":

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4 จะเพิ่มตัวเลือก -Gเพื่อให้คุณผ่าน -G <regexp> เพื่อค้นหาเมื่อมีการย้ายบรรทัดที่มี <regexp> ซึ่ง -S ไม่สามารถทำได้ -S จะบอกคุณเมื่อจำนวนบรรทัดทั้งหมดที่มีสตริงเปลี่ยนไป (เช่นการเพิ่ม / ลบสตริง)

ในที่สุดคุณสามารถใช้ gitk เพื่อให้เห็นภาพการผูกมัดด้วย:

gitk --all $(git log -g --pretty=format:%h)

จากนั้นใช้คุณลักษณะการค้นหาเพื่อค้นหาไฟล์ที่วางผิดตำแหน่ง งานทั้งหมดนี้สมมติว่าการคอมมิชชันที่หายไปไม่ได้ "หมดอายุ" และถูกเก็บขยะซึ่งอาจเกิดขึ้นหากมันห้อยอยู่เป็นเวลา 30 วันและคุณหมดอายุ reflogs หรือรันคำสั่งที่หมดอายุ


4
บางทีแทนที่จะเรียกใช้ "git grep" บนจำนวนคอมมิท (อาจมาก) ซึ่งจะหาคอมมิททั้งหมดที่มี 'search_for_this' อยู่ที่ใดที่หนึ่งในโครงการให้ใช้ที่เรียกว่าการค้นหา "pickaxe" เช่นตัวเลือก 's' เพื่อบันทึกคอมไพล์ ซึ่งพบการกระทำที่แนะนำหรือลบสตริงที่กำหนดหรือจะแม่นยำมากขึ้นเมื่อจำนวนการเกิดขึ้นของสตริงที่กำหนดเปลี่ยนไป
Jakub Narębski

5
คุณสามารถระบุหลายสาขาหรือใช้ตัวเลือก '--all' เช่น 'git log --grep = "string ในข้อความคอมมิท"
Jakub Narębski

เพียงแค่อนุญาตให้ฉันค้นหาความผิดพลาดที่หายไปจากการทำงาน 2 วัน บันทึกตูดของฉันทั้งหมดขอบคุณ!
Mike Chamberlain

2
ฉันเจอสถานการณ์บางอย่างที่ฉันได้กระทำในฐานข้อมูลของฉัน แต่ไม่ได้อยู่ในการอ้างอิงของฉัน ฉันไม่รู้ว่ามันเป็นเรื่องธรรมดา ฉันลองใช้สะพาน hg / git ที่แตกต่างกัน ฉันคิดว่ามันสามารถเกิดขึ้นได้เมื่อมีการกระตุก ไม่ว่าในกรณีใดนามแฝงนี้จะใช้งานได้ดีในการจับกรณีเหล่านั้น:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
dubiousjim

หมายเหตุที่ไม่รวมการค้นหาวัตถุบันทึกย่อ ที่ยังไม่ได้ใช้งาน: git.661346.n2.nabble.com/…
Antony Stubbs

54

ใน Mercurial คุณใช้hg log --keywordเพื่อค้นหาคำหลักในข้อความยืนยันและhg log --userเพื่อค้นหาผู้ใช้รายใดรายหนึ่ง ดูhg help logวิธีอื่น ๆ ในการ จำกัด การบันทึก


36
Josip เขียนว่าเขากำลังพิจารณาที่จะเปลี่ยนมาใช้ Mercurial และเขาก็อยากจะได้ยินว่ามันทำอย่างไรที่นั่น
Martin Geisler

1
hg log -kการค้นหาใช้ชื่อผู้ใช้และชื่อไฟล์ในเซ็ตการแก้ไขเช่นกัน (ฉันเห็นว่าใน orders.py:log) ซึ่งเป็นหนึ่งในสองสามสิ่งที่ฉันไม่เข้าใจใน hg ควรมีตัวเลือกแยกต่างหากในการค้นหาข้อความและชื่อไฟล์ ดูเหมือนว่าhg log --template '{desc}\n'|grepเป็นวิธีที่แน่นอน
เจฟฟรีย์เจิ้ง

@GeoffreyZheng: มีวิธีการทำเช่นนั้น โปรดดูที่ "hg help revsets", ฟังก์ชั่น desc (), user (), และ file () นอกจากนี้ยังมีสวิตช์บันทึก hg สำหรับพฤติกรรมส่วนใหญ่ จากประสบการณ์ของฉันแม้ว่า -k / keyword () มักเป็นวิธีที่มีประโยชน์ที่สุดในการค้นหาสิ่งต่าง ๆ
เควินฮอร์น

หนึ่งค้นหาผ่านเนื้อหาไฟล์ที่เกิดขึ้นจริง ... แตกต่างอย่างไร ฉันรู้ว่ามันเป็นการค้นหาที่ช้า แต่ฉันต้องการค้นหาชื่อฟังก์ชันที่หายไปอย่างละเอียด
Jonathan

โอ้นี่hg grep --all <term>
Jonathan

24

นอกจากคำตอบ richqของการใช้git log -g --grep=<regexp>หรือgit grep -e <regexp> $(git log -g --pretty=format:%h): ดูที่บล็อกโพสต์ต่อไปนี้โดย Junio ​​C Hamano ผู้ดูแลคอมไพล์ปัจจุบัน


สรุป

ทั้งgit grepและgit log --grepเป็นบรรทัดที่มีการค้นหาบรรทัดที่ตรงกับรูปแบบที่ระบุ

คุณสามารถใช้git log --grep=<foo> --grep=<bar>(หรือgit log --author=<foo> --grep=<bar>แปลเป็นสองภายใน--grep) เพื่อค้นหาการกระทำที่ตรงกับรูปแบบใดรูปแบบหนึ่ง (โดยนัยหรือความหมาย)

เนื่องจากเป็นการเน้นบรรทัดดังนั้นAND AND semantic จึงเป็นประโยชน์git log --all-match --grep=<foo> --grep=<bar>ในการค้นหาคอมมิตที่มีทั้งการจับคู่บรรทัดแรกและการจับคู่บรรทัดที่สองที่ใดที่หนึ่ง

ด้วยgit grepคุณสามารถรวมรูปหลาย ๆ (ทั้งหมดซึ่งจะต้องใช้-e <regexp>แบบฟอร์ม) กับ--or(ซึ่งเป็นค่าเริ่มต้น) --and, --not, และ( )สำหรับ grep --all-matchหมายความว่าไฟล์นั้นจะต้องมีบรรทัดที่ตรงกับตัวเลือกแต่ละตัว


เฮ้ยาคุบใจที่รวมคำพูด / บทสรุปจากการโพสต์บล็อกเหล่านี้ไว้ที่นี่? ดูเหมือนว่าหนึ่งในคำตอบลิงก์วินเทจเท่านั้นในตอนนี้
Nathan Tuggy

11

จากคำตอบของ rq ฉันพบว่าบรรทัดนี้ทำในสิ่งที่ฉันต้องการ:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

ซึ่งจะรายงานรหัสการกระทำชื่อไฟล์และแสดงบรรทัดที่ตรงกันเช่นนี้:

91ba969:testFile:this is a test

... ไม่มีใครยอมรับว่านี่เป็นตัวเลือกที่ดีที่จะรวมอยู่ในคำสั่ง git grep มาตรฐานหรือไม่


5

คำสั่งใด ๆ ที่รับการอ้างอิงเป็นอาร์กิวเมนต์จะยอมรับ--allตัวเลือกที่บันทึกไว้ในหน้าคนgit rev-listดังต่อไปนี้:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

ตัวอย่างเช่นgit log -Sstring --allจะแสดงการกระทำทั้งหมดที่กล่าวถึงstringและสามารถเข้าถึงได้จากสาขาหรือจากแท็ก (ฉันสมมติว่าการผูกมัดห้อยของคุณมีชื่ออย่างน้อยด้วยแท็ก)


3
นี้จะไม่ปรากฏเป็นกรณีสำหรับgit grepที่--allจะปรากฏขึ้นที่จะได้รับการแปลเป็นภาษา / --all-matchใช้เป็น ดูเหมือนว่าเป็นข้อบกพร่องสำหรับฉัน .. โดยใช้ Git 1.7.2.3 (ใช้$(git rev-list --all)งาน)
blueyed

5

ด้วย Mercurial คุณทำได้

$ hg grep "search for this" [file...]

มีตัวเลือกอื่น ๆ ที่ จำกัด ช่วงการแก้ไขที่ค้นหา


1
ฉันชอบธงhg grep --all
Jonathan

2

ไม่ทราบเกี่ยวกับคอมไพล์ แต่ใน Mercurial ฉันเพียงแค่ส่งออกบันทึก hg ไปยัง sed / perl / สคริปต์อะไรก็ตามที่จะค้นหาสิ่งที่คุณต้องการ คุณสามารถปรับแต่งเอาต์พุตของบันทึก hg โดยใช้เทมเพลตหรือสไตล์เพื่อให้ค้นหาได้ง่ายขึ้นถ้าคุณต้องการ

ซึ่งจะรวมถึงสาขาที่มีชื่อทั้งหมดใน repo Mercurial ไม่มีอะไรที่เหมือนห้อย blobs afaik


1
ฉันไม่เข้าใจว่าคำตอบนี้เกี่ยวข้องกับปัญหาที่ระบุหรือไม่
jribeiro

3
มันเป็นคำตอบสำหรับคำถามของ Mercurial ซึ่งคำถามดั้งเดิมถามในย่อหน้าสุดท้าย
Kurt Schelfthout


1

ในการเพิ่มโซลูชันอีกหนึ่งตัวที่ยังไม่ได้กล่าวถึงฉันต้องบอกว่าการใช้ช่องค้นหาแบบกราฟิกของ gitg เป็นวิธีที่ง่ายที่สุดสำหรับฉัน มันจะเลือกเหตุการณ์ที่เกิดขึ้นครั้งแรกและคุณสามารถค้นหาต่อไปด้วย Ctrl-G


1

หนึ่งคำสั่งในคอมไพล์ที่ฉันคิดว่ามันง่ายกว่าการหาสตริง:

git log --pretty=oneline --grep "string to search"

ทำงานใน Git 2.0.4

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