Git - मैं किसी विधि / फ़ंक्शन के परिवर्तन इतिहास को कैसे देखूँ?


93

इसलिए मुझे इस सवाल का पता चला कि किसी फ़ाइल के इतिहास को कैसे देखा जाए, लेकिन इस विशेष फ़ाइल का परिवर्तन इतिहास बहुत बड़ा है और मैं वास्तव में किसी विशेष पद्धति के परिवर्तनों में दिलचस्पी रखता हूं। तो क्या उस विशेष पद्धति के लिए परिवर्तन इतिहास देखना संभव होगा?

मुझे पता है कि इसके लिए कोड का विश्लेषण करने की आवश्यकता होगी और यह विश्लेषण अलग-अलग भाषाओं के लिए अलग-अलग होगा, लेकिन अधिकांश भाषाओं में विधि / कार्य घोषणाएं समान दिखती हैं, इसलिए मैंने सोचा कि शायद किसी ने इस सुविधा को लागू किया है।

मैं वर्तमान में जिस भाषा के साथ काम कर रहा हूं, वह ऑब्जेक्टिव-सी है और जिस एससीएम का मैं वर्तमान में उपयोग कर रहा हूं वह git है, लेकिन मुझे यह जानने में रुचि होगी कि क्या यह सुविधा किसी SCM / भाषा के लिए मौजूद है।


1
मैंने Git GSoG प्रस्ताव में ऐसी कार्यक्षमता देखी है।
वि।

क्या यह वह प्रस्ताव है जिसके बारे में आप बात कर रहे थे? सूचियाँ-archives.org/git/…
Erik B


@lpapp पर यहां प्रश्न 10 महीने पहले पूछा गया था, अन्य प्रश्न को इस एक के रूप में चिह्नित किया जाना चाहिए (यदि वे सभी पर नकल की जाती हैं)।
गंदा-प्रवाह

2
@lpapp वे दो बिल्कुल अलग सवाल हैं। आप संभवतः एक स्क्रिप्ट लिख सकते हैं जो एक फ़ंक्शन नाम को कई लाइनों के लिए हल करता है और फिर उन पंक्तियों के लिए इतिहास प्राप्त करने के लिए उस प्रश्न से तकनीक का उपयोग करता है, लेकिन अपने आप में इस प्रश्न का उत्तर नहीं देता है।
एरिक बी

जवाबों:


100

हाल के संस्करणों git logने -Lपैरामीटर के एक विशेष रूप को सीखा :

-L: <funcname>: <file>

"<start>,<end>"(या फ़ंक्शन नाम regex <funcname>) द्वारा दी गई रेखा श्रेणी के विकास को ट्रेस करें <file>। आप किसी भी pathspec की सीमा नहीं दे सकते हैं। यह वर्तमान में केवल एक संशोधन से शुरू होने तक चलने तक सीमित है, अर्थात, आप केवल शून्य या एक सकारात्मक संशोधन तर्क दे सकते हैं। आप इस विकल्प को एक से अधिक बार निर्दिष्ट कर सकते हैं।
...
यदि और के “:<funcname>”स्थान पर दिया जाता है , तो यह एक नियमित अभिव्यक्ति है जो पहली फंकनामे लाइन से उस श्रेणी को दर्शाता है जो मेल खाता है , अगली फनकैम लाइन तक। पिछली श्रेणी के अंत से खोजें , यदि कोई हो, अन्यथा फ़ाइल की शुरुआत से। फ़ाइल की शुरुआत से खोज करता है।<start><end><funcname>“:<funcname>”-L“^:<funcname>”

दूसरे शब्दों में: यदि आप Git से पूछते हैं git log -L :myfunction:path/to/myfile.c, तो यह अब उस फ़ंक्शन के परिवर्तन इतिहास को खुशी से प्रिंट करेगा।


16
यह बॉक्स से बाहर उद्देश्य-ग के लिए काम कर सकता है, लेकिन यदि आप अन्य भाषाओं (जैसे पायथन, रूबी आदि) के लिए ऐसा कर रहे हैं, तो आपको फ़ंक्शन / विधि को पहचानने के लिए git के लिए एक .गित्टाडेंजिस फ़ाइल के अंदर उपयुक्त कॉन्फ़िगरेशन जोड़ने की आवश्यकता हो सकती है। उस भाषा में घोषणाएं। अजगर के उपयोग के लिए * .py diff = अजगर, माणिक उपयोग के लिए * .rb diff = ruby
samaspin

1
फ़ंक्शन का पता कैसे लगाता है?
nn0p

@ nn0p मैं कई भाषाओं का वाक्यविन्यास ज्ञान रखता हूं और इस प्रकार किसी फ़ंक्शन को अलग करना और उसके परिवर्तनों का पता लगाना जानता हूं।
जेसनजेनएक्स

4
अन्य भाषाओं के लिए @ samaspin की टिप्पणी का विस्तार करते हुए, आप यहां डॉक्स का उल्लेख कर सकते हैं: git-scm.com/docs/gitattributes#_generating_diff_text
edhgoose

यह स्काला और जावा और यहां तक ​​कि सी जैसी भाषाओं के लिए काम नहीं करता है, जो नेस्टेड कर्ली ब्रेसिज़ का उपयोग करती हैं (नियमित अभिव्यक्ति सामान्य रूप से इसे संभाल नहीं सकती हैं), और यहां तक ​​कि प्रारंभ, अंत फ़ॉर्म तब काम नहीं करता है जब फ़ंक्शन फ़ाइल में ले जाया जाता है। और एक ही प्रतिबद्ध में संशोधित।
रॉबिन ग्रीन

16

उपयोग करना git gui blameकठिन है लिपियों का उपयोग करना, और whilst git log -Gऔर git log --pickaxeप्रत्येक दिखा सकता है जब विधि परिभाषा प्रकट हुई या गायब हो गई, तो मुझे उन्हें आपके तरीके के शरीर में किए गए सभी परिवर्तनों को सूचीबद्ध करने का कोई तरीका नहीं मिला है ।

हालांकि, आप उपयोग कर सकते हैं gitattributesऔर textconvसंपत्ति को एक समाधान के साथ टुकड़े करने के लिए जो बस करता है। हालाँकि ये सुविधाएँ मूल रूप से बाइनरी फ़ाइलों के साथ काम करने में आपकी मदद करने के लिए बनाई गई थीं, वे यहाँ भी काम करती हैं।

कुंजी को फ़ाइल से सभी लाइनों को हटाने के लिए है जो किसी भी अलग संचालन को करने से पहले आपकी रुचि के अलावा है। फिर git log, git diffआदि केवल उस क्षेत्र को देखेंगे जिसमें आप रुचि रखते हैं।

यहाँ मैं दूसरी भाषा में क्या करता हूँ इसकी रूपरेखा प्रस्तुत की गई है; आप इसे अपनी जरूरतों के लिए ट्वीक कर सकते हैं।

  • एक शॉर्ट शेल स्क्रिप्ट (या अन्य प्रोग्राम) लिखें जो एक तर्क लेता है - एक स्रोत फ़ाइल का नाम - और उस फ़ाइल के केवल दिलचस्प हिस्से को आउटपुट करता है (या अगर कुछ भी दिलचस्प नहीं है)। उदाहरण के लिए, आप sedनिम्नानुसार उपयोग कर सकते हैं :

    #!/bin/sh
    sed -n -e '/^int my_func(/,/^}/ p' "$1"
    
  • textconvअपनी नई स्क्रिप्ट के लिए एक Git फ़िल्टर परिभाषित करें । ( gitattributesअधिक विवरण के लिए मैन पेज देखें।) फ़िल्टर का नाम और कमांड का स्थान कुछ भी हो सकता है जिसे आप पसंद करते हैं।

    $ git config diff.my_filter.textconv /path/to/my_script
    
  • प्रश्न में फ़ाइल के लिए भिन्न होने से पहले उस फ़िल्टर का उपयोग करने के लिए गिट को बताएं।

    $ echo "my_file diff=my_filter" >> .gitattributes
    
  • अब, यदि आप अपने फ़िल्टर लागू होने पर दिखाई देने वाले परिवर्तनों को उत्पन्न करने वाले सभी कमिट्स को सूचीबद्ध करने के लिए -G.(नोट .) का उपयोग करते हैं, तो आपके पास वास्तव में वे कमिट होंगे जो आप में रुचि रखते हैं। कोई अन्य विकल्प जो गिट के अलग-अलग रूटीन का उपयोग करते हैं, जैसे कि --patch,। यह प्रतिबंधित दृश्य भी प्राप्त करें।

    $ git log -G. --patch my_file
    
  • देखा!

एक उपयोगी सुधार जो आप करना चाहते हैं, वह यह है कि आपके फ़िल्टर स्क्रिप्ट को पहले तर्क के रूप में एक विधि का नाम लेना चाहिए (और दूसरी के रूप में फ़ाइल)। यह आपको git configअपनी स्क्रिप्ट संपादित करने के बजाय केवल कॉल करके रुचि की एक नई विधि निर्दिष्ट करने देता है । उदाहरण के लिए, आप कह सकते हैं:

$ git config diff.my_filter.textconv "/path/to/my_command other_func"

बेशक, फ़िल्टर स्क्रिप्ट आपको जो कुछ भी पसंद है वह कर सकती है, अधिक तर्क ले सकती है, या जो भी हो: मैंने यहां जो दिखाया है, उससे परे बहुत अधिक लचीलापन है।


1
एक से अधिक तर्क मेरे लिए काम नहीं करते थे, लेकिन फ़ंक्शन नाम को कड़ी मेहनत में डाल देना ठीक है और यह वास्तव में बहुत बढ़िया है!
५१ पर क्वर्टीजगुई

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

12

git log में एक विकल्प है '-G' का उपयोग सभी अंतरों को खोजने के लिए किया जा सकता है।

-G उन अंतरों के लिए देखें जिनकी जोड़ी गई या निकाली गई रेखा दिए गए से मेल खाती है <regex>

बस इसे आप जिस फंक्शन नाम की परवाह करते हैं, उसका उचित रीगेक्स दें। उदाहरण के लिए,

$ git log --oneline -G'^int commit_tree'
40d52ff make commit_tree a library function
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
7b9c0a6 git-commit-tree: make it usable from other builtins

5
मैंने कमांड नहीं चलाया था, लेकिन मुझे ऐसा लग रहा है कि यह कमांड केवल उन कमिट्स को दिखाएगा जो कि रेक्स से मेल खाने वाली लाइन को छूते हैं, जो कि पूरी विधि / फ़ंक्शन नहीं है।
एरिक बी

यदि आप और अधिक संदर्भ चाहते हैं, आप बदल सकते हैं --onelineके साथ-p
lfender6445

3
लेकिन क्या होगा अगर एक बदलाव विधि में 20 लाइनें बनाई गईं?
nafg

+1। मेरे लिए, शीर्ष उत्तर ने काम किया लेकिन केवल सबसे हालिया प्रतिबद्धता दिखाई। संभवतः विद्रोह या फ़ंक्शन के कारण कुछ समय के बारे में, निश्चित नहीं है। फ़ंक्शन के बजाय कोड की वास्तविक लाइन की खोज करके यह इसमें था (एक-लाइनर के बावजूद) इस उत्तर ने मुझे आसानी से वह कमिटमेंट प्राप्त करने की अनुमति दी, जिसकी मुझे तलाश थी। शुक्र है कि मैं आमतौर पर उपयोगी प्रतिबद्ध संदेश लिखता हूं!
डेव एस

11

निकटतम चीज़ जो आप कर सकते हैं वह है फ़ाइल में अपने फ़ंक्शन की स्थिति निर्धारित करना (जैसे कि आपका फ़ंक्शन i_am_buggy241-263 की पंक्तियों में है foo/bar.c), फिर इसके प्रभाव के लिए कुछ चलाएँ:

git log -p -L 200,300:foo/bar.c

यह कम (या समकक्ष पेजर) खोलेगा। अब आप /i_am_buggy(या आपके पेजर समतुल्य) टाइप कर सकते हैं और परिवर्तनों के माध्यम से कदम बढ़ाना शुरू कर सकते हैं।

यह आपके कोड शैली के आधार पर भी काम कर सकता है:

git log -p -L /int i_am_buggy\(/,+30:foo/bar.c

यह उस regex (आदर्श रूप से आपके फ़ंक्शन की घोषणा) की पहली हिट से खोज को उसके बाद तीस लाइनों तक सीमित करता है। अंतिम तर्क भी एक regexp हो सकता है, हालांकि यह पता लगाना कि regexp के साथ एक iffier प्रस्ताव है।


मिठाई! FYI करें, यह Git v1.8.4 में नया है। (लगता है कि मुझे अपग्रेड करना चाहिए।) हालांकि एक अधिक सटीक समाधान अच्छा होगा ... जैसे कि किसी ने पॉल व्हिटाकर के जवाब को स्क्रिप्ट किया।
ग्रेग प्राइस

@GregPrice जाहिरा तौर पर खोज के किनारों को भी नियमित रूप से अभिव्यक्ति हो सकती है , इसलिए आप कम से कम सटीक या अधिक सटीक बिंदु रख सकते हैं।
बैड

ओह वाह। वास्तव में: आप अपने स्वयं के regexp को लिखने के बजाय केवल -L ":int myfunc:foo/bar.c"उस नाम के साथ फ़ंक्शन को कह सकते हैं और सीमित कर सकते हैं । यह शानदार है - पॉइंटर के लिए धन्यवाद! अब अगर केवल फंक्शन डिटेक्शन थोड़ा और विश्वसनीय था ...
ग्रेग प्राइस

3

सही तरीका यह है git log -L :function:path/to/fileकि eckes जवाब में बताया गया है ।

लेकिन इसके अलावा, यदि आपका फ़ंक्शन बहुत लंबा है, तो आप केवल उन परिवर्तनों को देखना चाहते हैं जो विभिन्न प्रतिबद्धताओं ने शुरू किए थे, न कि पूरे फ़ंक्शन लाइनों को शामिल किया, अनमॉडिफाइड, प्रत्येक प्रतिबद्ध के लिए कि शायद इनमें से केवल एक रेखा को स्पर्श करें। जैसे कोई सामान्य diffकरता है।

आम तौर पर git logसाथ मतभेद देख सकते हैं -p, लेकिन यह काम नहीं करता है -L। इसलिए आपको उन्हें शामिल करने के grep git log -Lलिए केवल शामिल लाइनों और कमिट / फाइल हेडर को दिखाना होगा। यहाँ चाल केवल टर्मिनल रंगीन लाइनों से मेल खाना है, --colorस्विच जोड़ना , रेगेक्स के साथ। आखिरकार:

git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3

ध्यान दें कि ^[वास्तविक, शाब्दिक होना चाहिए ^[। आप उन्हें 'V ^ [को bash में दबाकर टाइप कर सकते हैं, वह है Ctrl+ V, Ctrl+ [। संदर्भ यहाँ

इसके अलावा अंतिम -3स्विच, प्रत्येक मिलान किए गए लाइन से पहले और बाद में आउटपुट संदर्भ की 3 लाइनों को प्रिंट करने की अनुमति देता है। आप इसे अपनी आवश्यकताओं के लिए समायोजित करना चाह सकते हैं।


2

गिट दोष आपको दिखाता है कि आखिरी बार फ़ाइल की प्रत्येक पंक्ति को किसने बदला है; आप लाइनों की जांच कर सकते हैं ताकि आपके फ़ंक्शन के बाहर लाइनों के इतिहास को प्राप्त करने से बचें।


4
साथ git gui blameआप पुराने संशोधनों को नेविगेट कर सकते हैं।
वि।

0
  1. फ़ंक्शन इतिहास दिखाएं git log -L :<funcname>:<file>जैसा कि एक्केज़ के उत्तर और गिट डॉक में दिखाया गया है

    यदि यह कुछ नहीं दिखाता है, तो अपनी भाषा का समर्थन करने के लिए फ़ाइल जैसी कुछ जोड़ने के लिए एक कस्टम हंक-हेडर को परिभाषित करने का संदर्भ दें ।*.java diff=java.gitattributes

  2. के साथ कमिट्स के बीच फंक्शन हिस्ट्री दिखाएं git log commit1..commit2 -L :functionName:filePath

  3. अतिभारित फ़ंक्शन इतिहास दिखाएं (एक ही नाम के साथ कई फ़ंक्शन हो सकते हैं, लेकिन विभिन्न मापदंडों के साथ) git log -L :sum\(double:filepath

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