किसी फ़ाइल में किसी विशिष्ट पंक्ति के लिए प्रतिबद्ध लॉग पुनर्प्राप्त करें?


502

क्या आपको किसी फ़ाइल में किसी विशेष लाइन को छूने वाले कमिट के लिए कमिट लॉग देने का कोई तरीका है ?

जैसे git blame, लेकिन git blameआपको वह LAST कमिटमेंट दिखाएगा जो किसी विशेष लाइन को छूता है।

मैं वास्तव में एक समान लॉग प्राप्त करना चाहता हूं, न कि फ़ाइल में कहीं भी आने की सूची नहीं है, लेकिन सिर्फ वह कमिट करता है जो किसी विशेष लाइन को छूता है।


2
यह भी देखें: Git दोष - पूर्व
हिट्स

जवाबों:


631

Git भी देखें : जो खोजता है वह कभी लाइनों की एक सीमा को छूता है


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। कोई सुझाव?
बैरादेव

12
Git 1.8.4 या बाद में अपग्रेड करें।
मैट मैक्लर

4
क्या होगा यदि मैं जानना चाहता हूं कि "प्रतिबद्ध में लाइन 155 का इतिहास क्या है" (हेड में लाइन 155 के बजाय)। क्या मैं बस उपयोग कर सकता हूं git log commitA-hash -L 155,155:file-name?
इदा

@ अच्छा, मेरे पास एक मजबूत प्राथमिकता नहीं है।
मैट मैक्लर

यह अच्छी तरह से काम करता है, सिवाय इसके कि फ़ाइल को स्थानांतरित / नाम दिया गया है ... ऐसा लगता है कि --follow लाइन रेंज args के साथ संयुक्त होना पसंद नहीं करता है।
माइक एलरी

66

आप पिक-कुल्हाड़ी का उपयोग करके आवागमन का एक सेट प्राप्त कर सकते हैं।

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

यह आपको उस फ़ाइल में उस पाठ को प्रभावित करने वाले सभी आवागमन देगा। यदि किसी बिंदु पर फ़ाइल का नाम बदला गया था, तो आप --follow-parent को जोड़ सकते हैं।

यदि आप इनमें से प्रत्येक संपादन पर कमिट्स का निरीक्षण करना चाहते हैं, तो आप उस परिणाम को प्रदर्शित कर सकते हैं:

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

5
मुझे यकीन नहीं है कि मैं देखता हूं कि यह कैसे मदद करता है। यदि पाठ प्रभावित हुआ था, तो लाइन अब समान नहीं है, इसलिए पिकैक्स केवल आपको सबसे हाल का परिवर्तन दिखाएगा। आपको इसके बाद git log -S'the previous version of the line'ऐसा करना होगा, ठीक उसी तरह जैसे आप करना चाहते हैं git blame -L। और यह इस तरह से धीमा होगा git blame, क्योंकि इसमें दिए गए स्थान पर ही नहीं, हर जगह पाठ को देखना होगा।
Cascabel

इसे और अधिक स्वीकार करने के लिए आप इसमें रेगेक्स का उपयोग कर सकते हैं। वर्तमान में कुछ विस्तृत स्क्रिप्टिंग के बिना समय में "पैच के माध्यम से नेविगेट" करने का कोई तरीका नहीं है। मुझे उम्मीद है कि gitk को भविष्य में पैच दृश्य में यह कार्यक्षमता मिलेगी।
एडम डिमिट्रुक

3
इसे पिक-कुल्हाड़ी क्यों कहा जाता है ? :)
सिप्रियन टॉमोयागै

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। कृपया सही
विक Seedoubleyew

14

ऐसा करने का एक बहुत ही आसान तरीका है विम-फॉगिव का उपयोग करना । बस फ़ाइल को vim में खोलें, उस पंक्ति का चयन करें जिसे आप उपयोग करने में रुचि रखते हैं V, फिर दर्ज करें

:Glog

अब आप फ़ाइल का सभी संशोधन देख सकते हैं :cnextऔर :cprevउस पंक्ति को संशोधित कर सकते हैं। किसी भी बिंदु पर, :Gblameशा, लेखक और तिथि जानकारी देखने के लिए दर्ज करें।


13

सरलीकरण @ मैट का उत्तर -

git blame -L14,15 -- <file_path>

यहां आपको लाइनों के लिए दोष मिलेगा 14 to 15

के बाद से -Lविकल्प की उम्मीद Rangeका कोई पैरामीटर के रूप में हम एक नहीं मिल सकता है Blameका उपयोग करके एकरेखीय के लिए -Loption`

संदर्भ


10

मेरा मानना ​​है कि इसके लिए कुछ भी अंतर्निहित नहीं है। यह इस तथ्य से मुश्किल बना हुआ है कि एक ही लाइन के लिए कई बार फ़ाइल को बदलना बहुत ही कम है, बाकी फाइल भी काफी हद तक बदलती रहती है, इसलिए आप लाइन नंबर को बहुत बदलकर समाप्त कर देंगे।

यदि आप पर्याप्त भाग्यशाली हैं कि लाइन में हमेशा कुछ पहचान की विशेषता होती है, उदाहरण के लिए एक चर के लिए एक असाइनमेंट जिसका नाम कभी नहीं बदला है, तो आप के लिए regex पसंद का उपयोग कर सकते हैं git blame -L। उदाहरण के लिए:

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

लेकिन यह केवल पहले पाता है उस रेगेक्स के लिए मैच , इसलिए यदि आपके पास लाइन से मेल खाने का अच्छा तरीका नहीं है, तो यह बहुत उपयोगी नहीं है।

आप कुछ हैक कर सकते हैं, मुझे लगता है। मेरे पास अभी कोड लिखने का समय नहीं है, लेकिन ... इन पंक्तियों के साथ कुछ। भागो 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

यह एक बदसूरत वन-लाइनर है, इसलिए यहां एक डी-ऑबफसकेटेड समकक्ष बैश फ़ंक्शन है:

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
}

पिकैक्स समाधान ( git log --pickaxe-regex -S'REGEX ' ) आपको केवल पंक्ति जोड़ / विलोपन देगा, न कि नियमित अभिव्यक्ति वाले लाइन के अन्य परिवर्तन।

इस समाधान की एक सीमा यह है कि गिट दोष केवल 1 REGEX मैच लौटाता है, इसलिए यदि कई मैचों में मौजूद है तो दूसरी पंक्ति का अनुसरण करने के लिए पुनरावृत्ति "कूद" सकती है। उन "छलांग" को स्पॉट करने के लिए पूर्ण इतिहास आउटपुट की जांच करना सुनिश्चित करें और फिर परजीवी लाइनों को अनदेखा करने के लिए अपने REGEX को ठीक करें।

अंत में, यहां एक वैकल्पिक संस्करण है जो पूर्ण भिन्नता प्राप्त करने के लिए प्रत्येक प्रतिबद्ध पर गिट शो चलाता है :

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 blameऔर git logकमांड कर सकते हैं। निम्नलिखित बैश + अक्क स्क्रिप्ट की तरह कुछ। यह कोड टिप्पणी इनलाइन के रूप में प्रतिबद्ध सारांश को जोड़ता है।

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 पर भी था जो "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>"

यह निश्चित रूप से एक स्क्रिप्ट या फ़ंक्शन में बनाया जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.