2008-11-10 15 views
51

बस कहें कि मेरे पास एक फ़ाइल है: एक गिट भंडार के भीतर कई उपनिर्देशिकाओं में "HelloWorld.pm"।क्या मैं भंडार में मिलान करने वाले फ़ाइल नामों को खोजने के लिए गिट का उपयोग कर सकता हूं?

मैं कोई आदेश जारी करने "HelloWorld.pm" मिलान सभी फाइलों का पूरा पथ को खोजने के लिए करना चाहते हैं:

उदाहरण के लिए:

/path/to/repository/HelloWorld.pm 
/path/to/repository/but/much/deeper/down/HelloWorld.pm 
/path/to/repository/please/dont/make/me/search/through/the/lot/HelloWorld.pm 

मैं Git का उपयोग कैसे कुशलतापूर्वक सब को खोजने के लिए कर सकते हैं एक पूर्ण फ़ाइल नाम से मेल खाने वाले पूर्ण पथ?

मुझे एहसास है कि मैं इसे लिनक्स/यूनिक्स खोज आदेश के साथ कर सकता हूं लेकिन मैं फ़ाइल उपनामों के उदाहरणों की तलाश में सभी उपनिर्देशिका स्कैनिंग से बचने की उम्मीद कर रहा था।

उत्तर

19

प्रयास करें:

git ls-tree -r HEAD | grep HelloWorld.pm 
+1

में या विंडोज पर दिखाया गया है: Git ls-वृक्ष -r HEAD '| findstr HelloWorld.pm' –

79

git ls-files आप भंडार में सभी फाइलों की एक सूची दे देंगे। आप उस पैटर्न से मेल खाने वाली फाइलें प्राप्त करने के लिए एक पैटर्न पास कर सकते हैं।

git ls-files '*/HelloWorld.pm' 

आप अपनी सामग्री के माध्यम से फ़ाइलें और ग्रेप का एक सेट प्राप्त करना चाहते हैं, तो आप ऐसा कर सकते हैं git grep साथ:

git grep some-string -- '*/HelloWorld.pm' 
+0

ls-files भी एक पैटर्न ले सकते हैं। –

+0

@jleedev आह, ठीक है। इसे सरल बनाने और 'git grep' में पैटर्न के साथ एक समस्या को ठीक करने के लिए मेरा उत्तर अपडेट किया गया। –

+0

(परेशान है, इसे [pathspec] (http://www.kernel.org/pub/software/scm/git/docs/gitglossary.html#def_pathspec) gitglossary (7) में कहा जाता है, लेकिन उस शब्द का लगातार उपयोग नहीं किया जाता है अन्यत्र।) –

38

हम्म, मूल प्रश्न भंडार के बारे में था। एक भंडार में 1 से अधिक प्रतिबद्ध होते हैं (सामान्य मामले में कम से कम), लेकिन केवल एक प्रतिबद्धता के माध्यम से खोज से पहले दिए गए उत्तर।

क्योंकि मुझे ऐसा कोई जवाब नहीं मिला जो वास्तव में पूरे प्रतिबद्धता इतिहास की खोज करता है, मैंने एक त्वरित ब्रूट फोर्स स्क्रिप्ट गिट-फाइ-बाय-नाम लिखा है जो लगभग (लगभग) सभी विचारों को ध्यान में रखता है।

#! /bin/sh 
tmpdir=$(mktemp -td git-find.XXXX) 
trap "rm -r $tmpdir" EXIT INT TERM 

allrevs=$(git rev-list --all) 
# well, nearly all revs, we could still check the log if we have 
# dangling commits and we could include the index to be perfect... 

for rev in $allrevs 
do 
    git ls-tree --full-tree -r $rev >$tmpdir/$rev 
done 

cd $tmpdir 
grep $1 * 

शायद एक और शानदार तरीका है।

कृपया पैरामीटर को grep में पारित करने के छोटे तरीके को नोट करें, इसलिए यह फ़ाइल नाम के कुछ हिस्सों से मेल खाएगा। यदि वह वांछित नहीं है तो अपनी खोज अभिव्यक्ति एंकर करें और/या उपयुक्त grep विकल्प जोड़ें।

गहरे इतिहास के लिए आउटपुट बहुत शोर हो सकता है, मैंने एक ऐसी स्क्रिप्ट के बारे में सोचा जो को एक श्रेणी में संशोधनों की एक सूची में परिवर्तित करता है, जैसे कि गिट रेव-लिस्ट क्या कर सकता है। लेकिन अब तक यह एक विचार बना रहा है।

+1

इस महान उत्तर के लिए बहुत बहुत धन्यवाद। यह मेरा दिन बचाया। काश मैं आपको और अधिक बढ़ा सकता हूं। –

+0

ग्रेट स्क्रिप्ट। हालांकि मैं इसका उपयोग करने में असमर्थ था क्योंकि मेरी गिट रेपो इतनी बड़ी है कि लिपि ने मेरी हार्ड ड्राइव में बाढ़ डाली :( –

+0

@ आर्नेबॉकमैन बस grep कमांड को अंतिम लूप में ले जाएं और प्रत्येक grep के बाद सब कुछ हटा दें। –

3

[यह टिप्पणी की दुर्व्यवहार का एक सा है, मैं मानता हूँ, लेकिन मैं अभी तक कोई टिप्पणी नहीं कर सकते हैं और सोचा था कि मैं @ उवे-geuder के जवाब में सुधार होगा।]

#!/bin/bash 
# 
# 

# I'm using a fixed string here, not a regular expression, but you can easily 
# use a regular expression by altering the call to grep below. 
name="$1" 

# Verify usage. 
if [[ -z "$name" ]] 
then 
    echo "Usage: $(basename "$0") <file name>" 1>&2 
    exit 100 
fi 

# Search all revisions; get unique results. 
while IFS= read rev 
do 
    # Find $name in $rev's tree and only use its path. 
    grep -F -- "$name" \ 
     <(git ls-tree --full-tree -r "$rev" | awk '{ print $4 }') 
done < \ 
    <(git rev-list --all) \ 
    | sort -u 
फिर

, +1 करने के लिए @ उवे-geuder एक महान जवाब के लिए।

आप मार अपने आप में रुचि रखते हैं:

जब तक आप शब्द-बंटवारे की एक में पाश के लिए (जब इस तरह एक सरणी का उपयोग कर के रूप में: for item in "${array[@]}") की गारंटी कर रहे हैं, मैं अत्यधिक while IFS= read var ; do ... ; done < <(command) जब उपयोग करने की अनुशंसा कमांड आउटपुट जिसे आप लूपिंग कर रहे हैं उसे न्यूलाइन (या read -d'' से अलग किया जाता है जब आउटपुट को नल स्ट्रिंग $'\0') से अलग किया जाता है। जबकि git rev-list --all 40-बाइट हेक्साडेसिमल स्ट्रिंग्स (रिक्त स्थान के बिना) का उपयोग करने की गारंटी है, मैं कभी भी संभावना नहीं लेना चाहता हूं।अब मैं git rev-list --all से कमांड को आसानी से बदल सकता हूं जो

उत्पादित करता है मैं अस्थायी फ़ाइलों के बजाय इनपुट और फ़िल्टर आउटपुट इंजेक्ट करने के लिए अंतर्निहित बाश तंत्र का उपयोग करने की भी अनुशंसा करता हूं।

+0

सुनिश्चित नहीं है कि इतनी प्रक्रिया प्रतिस्थापन का उपयोग क्यों किया जा रहा है, जब आप आसानी से पाइप कर सकते हैं: 'git rev-list --all | rev पढ़ने के दौरान; do; git ls-tree --full-tree -आर $ rev | cut -c54- | fgrep - "$ name"; किया गया | sort -u' –

7
git ls-files | grep -i HelloWorld.pm 

grep -i grep केस असंवेदनशील बनाता है।

0

उवे जिउडर (@ uwe-geuder) द्वारा लिपि गई महानता है, लेकिन वास्तव में अपनी प्रत्येक निर्देशिका में एलएस-पेड़ आउटपुट को डंप करने की आवश्यकता नहीं है, unfiltered।

अधिक तेज और कम भंडारण का उपयोग कर: उत्पादन पर ग्रेप भागो और फिर इसे स्टोर, के रूप में यह gist

संबंधित मुद्दे

 संबंधित मुद्दे