ฉันจะค้นหาไฟล์หรือไดเรกทอรีสาขาของ Git ได้อย่างไร?


323

ใน Git ฉันจะค้นหาไฟล์หรือไดเรกทอรีตามเส้นทางข้ามสาขาได้อย่างไร?

ฉันเขียนบางสิ่งในสาขา แต่ฉันจำไม่ได้ว่าอันไหน ตอนนี้ฉันต้องการค้นหามัน

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


ฉันไม่แน่ใจเกี่ยวกับคำถาม ไฟล์นี้เป็นสาขาที่ถูกลบตอนนี้หรือไม่? ไฟล์ถูกลบหรือไม่
Abizern

คำตอบ:


444

git log+ git branchจะค้นหาให้คุณ:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <dustin@spy.net>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

รองรับ globbing เช่นกัน:

% git log --all -- '**/my_file.png'

จำเป็นต้องใช้อัญประกาศเดี่ยว (อย่างน้อยถ้าใช้ Bash shell) ดังนั้นเชลล์ส่งผ่านรูปแบบ glob เพื่อ git ไม่เปลี่ยนแปลงแทนที่จะขยายมัน (เช่นเดียวกับ Unix find)


2
วิธีนี้ใช้ได้ผลถ้าคุณรู้เส้นทางที่แน่นอนไปที่somefile: หากคุณต้องการค้นหา regex เหนือเส้นทาง / ชื่อไฟล์คุณสามารถใช้คำตอบของ ididak ได้
ShreevatsaR

70
รองรับ globbing เช่นกัน:git log --all -- **/my_file.png
webmat

3
ฉันใช้มันสำหรับปัญหาที่แตกต่างกันเล็กน้อย ฉันพยายามค้นหาไฟล์ * .sql ทั้งหมดที่ฉันให้ไว้กับสาขาเฉพาะ git log --grep='branch' --author='me' -- *.sqlดังนั้นผมจึงใช้ ทำงานเหมือนจับใจ git เวอร์ชั่น 1.7.11.1
thepriebe

1
โปรดทราบว่าgitkรองรับ globbing เช่นกัน นั่นเป็นคำตอบที่ยอดเยี่ยม @webmat! หากคุณต้องการดูว่ามันถูกลบ / สร้าง / ฯลฯ คุณสามารถใช้git log --all --stat -- **/my_file.pngวิธีที่คุณไม่ต้องเดาว่าคุณกำลังตรวจสอบจากการกระทำที่ถูกลบมัน
eacousineau

1
@webmat: ฉันใช้เสรีภาพในการเพิ่มข้อมูลของคุณเกี่ยวกับการทำให้กลมกลืนกับคำตอบ ขอบคุณที่พูดถึงมัน!
sleske

65

gs ls-tree อาจช่วยได้ วิธีค้นหาจากสาขาที่มีอยู่ทั้งหมด:

for branch in `git for-each-ref --format="%(refname)" refs/heads`; do
  echo $branch :; git ls-tree -r --name-only $branch | grep '<foo>'
done

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


3
ความคิดเห็นที่เป็นประโยชน์หวังว่าบางอย่าง: (a) คุณอาจต้องการเพิ่ม "-r" เป็น "git ls-tree" เพื่อให้สามารถค้นหาไฟล์ได้แม้ว่าจะอยู่ในไดเรกทอรีย่อย (b) อาจเป็นทางเลือกที่ neater บรรทัดแรกคือการใช้ "git สำหรับแต่ละอ้างอิง" เช่น "สำหรับสาขาในgit for-each-ref --format="%(refname)" refs/headsทำ" (c) "git ls-tree - ชื่อ - เท่านั้น" จะทำให้ผลลัพธ์ tidier (d) มันอาจคุ้มค่าที่จะชี้ให้เห็นในคำตอบของคุณว่ามันมีข้อดีของการแก้ปัญหาของดัสตินกล่าวคือคุณไม่จำเป็นต้องรู้ชื่อไฟล์อย่างแน่นอน - คุณสามารถค้นหาโดยใช้นิพจน์ปกติที่ตรงกับส่วนใดส่วนหนึ่งของเส้นทาง
Mark Longair

9
ฉันรวบรวมมันไว้ในสคริปต์เพื่อให้คุณสามารถเรียกใช้ "gitfind.sh <regex>"; ส่วนสำคัญคือgist.github.com/62d981890eccb48a99dc
Handyman5

3
โปรดทราบว่าสิ่งนี้จะค้นหาเฉพาะในสาขาท้องถิ่น หากต้องการค้นหาระยะไกลติดตามสาขาใช้แทนrefs/remotes refs/headsในการค้นหาทุกอย่าง (สาขาท้องถิ่นสาขาระยะไกลติดตามและแท็ก) refs/การใช้งานเพียงแค่
sleske

19

แม้ว่าการตอบสนองของ ididakจะค่อนข้างดีและHandyman5มีสคริปต์ให้ใช้ แต่ฉันพบว่ามีข้อ จำกัด เล็กน้อยในการใช้วิธีการดังกล่าว

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

คอมไพล์หาไฟล์

for branch in $(git rev-list --all)
do
  if (git ls-tree -r --name-only $branch | grep --quiet "$1")
  then
     echo $branch
  fi
done

คอมไพล์หาไฟล์-ละเอียด

for branch in $(git rev-list --all)
do
  git ls-tree -r --name-only $branch | grep "$1" | sed 's/^/'$branch': /'
done

ตอนนี้คุณสามารถทำได้

$ git find-file <regex>
sha1
sha2

$ git find-file-verbose <regex>
sha1: path/to/<regex>/searched
sha1: path/to/another/<regex>/in/same/sha
sha2: path/to/other/<regex>/in/other/sha

ดูว่าการใช้getoptคุณสามารถแก้ไขสคริปต์เพื่อสลับการค้นหาคอมมิทการอ้างอิงการอ้างอิง / หัวรับ verbose ทั้งหมด

$ git find-file <regex>
$ git find-file --verbose <regex>
$ git find-file --verbose --decorated --color <regex>

ชำระเงินhttps://github.com/albfan/git-find-fileเพื่อการใช้งานที่เป็นไปได้


คุณหมายถึง "ตอนนี้คุณสามารถทำ git-find-file <regex>" ได้ไหม ฉันทำงานได้แล้วขอบคุณ!
Elijah Lynn

1
ฉันเองพบว่ามีประโยชน์มากกว่าการใช้ $ (สาขา git | cut -c 3-) แทน $ (git rev-list - all) ฉันไม่สนใจที่จะหาคำมั่นสัญญาฉันสนใจสาขาที่มีชื่อ
Campadrenalin

ฉันยังเปลี่ยนสคริปต์เพื่อใช้ $ (สาขา git | cut -c 3-) เนื่องจากการวนซ้ำของการคอมมิททั้งหมดช้าเกินไป
i4h

เห็นเอะอะทั้งหมดที่ฉันมีสิ่งที่คุ้มค่าที่จะสร้าง repo สำหรับเรื่องนี้ github.com/albfan/git-find-file ฉันได้เปิดบางประเด็นอย่าลังเลที่จะเสนอเพิ่มเติมหรือส่งการประชาสัมพันธ์
albfan

1
@lumbric สคริปต์การติดตั้งบนเส้นทางใช้งานได้นอกกรอบคุณลักษณะของคอมไพล์
albfan

10

คุณสามารถใช้gitk --allและค้นหา "เส้นทางสัมผัส" และชื่อพา ธ ที่คุณสนใจ


3
ตามที่ระบุไว้ใช้ gitk - ทั้งหมดจากนั้นในมุมมอง | มุมมองใหม่เปิดใช้งานทุกสาขา จากนั้นตั้งค่าเกณฑ์การค้นหาของคุณ: ชื่อไฟล์ (พร้อมไวด์การ์ด) ในฟิลด์ถัดไป ในที่สุด: ตกลง
MikeW

8

คัดลอกและวางสิ่งนี้เพื่อใช้ git find-file SEARCHPATTERN

การพิมพ์สาขาที่ค้นหาทั้งหมด:

git config --global alias.find-file '!for branch in `git for-each-ref --format="%(refname)" refs/heads`; do echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; done; :'

พิมพ์เฉพาะสาขาที่มีผลลัพธ์:

git config --global alias.find-file '!for branch in $(git for-each-ref --format="%(refname)" refs/heads); do if git ls-tree -r --name-only $branch | grep "$1" > /dev/null; then  echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; fi; done; :'

คำสั่งเหล่านี้จะเพิ่มสคริปต์เชลล์ขั้นต่ำลง~/.gitconfigในนามแฝง git ทั่วโลกโดยตรง


มันเป็นเพียงการค้นหาในสาขาหลัก
Nasif Imtiaz Ohi

ค้นหาในสาขาท้องถิ่นทั้งหมด
Leonardo Herrera

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