किसी दिए गए फ़ाइल में परिवर्तन करने वाली एक Git शाखा खोजें


88

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

जवाबों:


87

उन सभी शाखाओं को खोजें जिनमें FILENAME का परिवर्तन होता है (भले ही (गैर-दर्ज की गई) शाखा बिंदु से पहले)

FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u

मैन्युअल रूप से निरीक्षण करें:

gitk --all --date-order -- $FILENAME

FILENAME के ​​सभी परिवर्तन मास्टर में विलय नहीं करें:

git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read x h; do if [ "`git log -n 1 --format=%H $h -- $FILENAME`" = "$h" ]; then echo $br; fi; done; done | sort -u

क्या मुझे FILENAME के ​​अलावा इस कमांड में कुछ भी बदलने की आवश्यकता है? यह सभी 57 शाखा नामों को लौटाता है।
डस्टिन

@ डस्टिन: यदि सभी 57 शाखाओं में वह फ़ाइल नाम होता है, तो सभी 57 शाखाओं में एक परिवर्तन होता है जिसमें वह फ़ाइल नाम शामिल होता है। शाखाएं उस शाखा पर उपलब्ध सबसे पुराने संशोधन से शुरू होती हैं, भले ही आपके द्वारा शाखा बनाए जाने से पहले वह संशोधन मौजूद हो (शाखा कुछ इंद्रियों में पूर्वव्यापी रूप से बनाई गई है)। मुझे लगता है कि आपको अपनी समस्या को बेहतर ढंग से परिभाषित करने की आवश्यकता है। क्या आप जानते हैं कि बदलाव क्या है? क्या आप उपयोग कर सकते हैं git log -Schange …या git log --grep LOGMESSAGE …(साथ… शेष कमांड का उल्लेख करते हैं)।
सेथ रॉबर्टसन

2
@ डस्टिन: एक अन्य विकल्प का उपयोग करना है, gitk --all -- filenameजो ग्राफिक रूप से आपको उस फ़ाइल के सभी परिवर्तनों को दिखाएगा। यदि आप प्रश्न में प्रतिबद्ध की पहचान कर सकते हैं, तो आप यह git branch --containsदेखने के लिए उपयोग कर सकते हैं कि प्रतिबद्ध किन शाखाओं में स्थानांतरित हो गए हैं। यदि आप यह देखना चाहते हैं कि मूल रूप से किस शाखा में प्रश्न किया गया था , तो Google git-what-Branch पर बनाया गया था , लेकिन इस बात से अवगत रहें कि तेजी से अग्रेषित विलय उस जानकारी को अस्पष्ट कर सकता है।
सेठ रॉबर्टसन

@ सेठ: मैं प्रतिबद्ध संदेश या सटीक कोड परिवर्तन याद नहीं कर सका। मेरे पास बस एक सामान्य विचार है। समस्या यह है कि इसे अभी तक मास्टर के साथ विलय नहीं किया गया है, इसलिए गिटक का उपयोग करने के लिए मुझे अभी भी प्रत्येक शाखा को जांचना होगा कि मैं क्या ढूंढ रहा हूं। यह अच्छा होगा अगर मैं कह सकता हूं, "मुझे, अपनी शाखाओं के बाद से FILENAME में परिवर्तन करने वाली शाखाएं दिखाएं"
डस्टिन

1
आप पहली पंक्ति को और अधिक कुशलता से लिख सकते हैंgit log --all --format='--contains %H' "$file" | xargs git branch
kojiro

52

जो तुम्हे चाहिए वो है

git log --all -- path/to/file/filename

यदि आप अभी शाखा जानना चाहते हैं तो आप भी उपयोग कर सकते हैं:

git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}

इसके अलावा, अगर आपका कोई नाम था, तो आप --followGit लॉग कमांड के लिए शामिल करना चाह सकते हैं ।


15
वह कमिट्स दिखाएगा, लेकिन उसने पूछा कि कौन सी ब्रांच है। --sourceवहाँ पर जोड़ें और आप सुनहरे हैं।
कार्ल बेवफेल्ट

धन्यवाद, लेकिन मुझे नहीं लगता है कि प्रत्येक प्रतिबद्ध के लिए सभी शाखाओं को दर्शाता है। लेकिन इससे मदद मिलेगी।
एडम डाइमिट्रुक

1
सच है, लेकिन इस विशेष मामले में वह केवल एक की तलाश में था।
कार्ल बेवफेल्ट

asp.net पथ के लिए btw AppName / नियंत्रकों / XController.cs की तरह प्रारूप में होना चाहिए
अली

8

ऐसा लगता है कि उचित समाधान के बिना यह अभी भी एक समस्या है। मेरे पास टिप्पणी करने के लिए पर्याप्त क्रेडिट नहीं है, इसलिए यहां मेरा थोड़ा योगदान है।

सेठ रॉबर्टसन के 1 समाधान थोड़े ने मेरे लिए काम किया, लेकिन केवल मुझे स्थानीय शाखाएं दीं, जिनमें कई झूठी सकारात्मकताएं थीं, शायद इसलिए स्थिर शाखा से विलय के कारण।

एडम डाइमिट्रुक का दूसरा समाधान मेरे लिए बिल्कुल भी कारगर नहीं था। शुरुआत के लिए, क्या --format =% 5 है? यह git द्वारा मान्यता प्राप्त नहीं है, मुझे इसके बारे में कुछ भी नहीं मिला और मैं इसे अन्य प्रारूप विकल्पों के साथ काम करने के लिए नहीं प्राप्त कर सका।

लेकिन उनका पहला समाधान - स्रोत विकल्प और एक साधारण grep के साथ संयुक्त मददगार साबित हुआ:

git log --all --source -- <filename> | grep -o "refs/.*" | sort -u

यह मुझे कई दूरस्थ टैग और शाखाएँ और एक स्थानीय शाखा देता है, जहाँ मैंने फ़ाइल में नवीनतम परिवर्तन किए हैं। निश्चित नहीं है कि यह पूरा कैसे हुआ।

हाल के बदलाव से शाखाओं को छाँटने के लिए @nealmcb के अनुरोध के अनुसार अद्यतन करें :

सबसे पहले, आप grep को "refs / heads /.*" में बदल सकते हैं, जो आपको केवल स्थानीय शाखाएँ देगा। यदि कुछ ही शाखाएँ हैं, तो आप इस तरह से हर एक की नवीनतम प्रतिबद्ध की जाँच कर सकते हैं:

git log -1 <branch> -- <filename>

यदि अधिक शाखाएं हैं और आप वास्तव में इसे स्वचालित करना चाहते हैं, तो आप xargs, git लॉग फॉर्मेटिंग और इस एक-लाइनर में एक अन्य प्रकार का उपयोग करके दो कमांड जोड़ सकते हैं:

git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r

यह इस तरह उत्पादन में परिणाम होगा:

2020-05-07T15:10:59+02:00 refs/heads/branch1
2020-05-05T16:11:52+02:00 refs/heads/branch3
2020-03-27T11:45:48+00:00 refs/heads/branch2

बहुत बहुत धन्यवाद। अब हाल के बदलाव से कैसे छंटनी होगी?
nealmcb

1

मुझे पता है कि यह सवाल प्राचीन है, लेकिन मैं अपना समाधान विकसित करने से पहले वापस आना शुरू कर दिया। मुझे लगता है कि यह अधिक सुरुचिपूर्ण है और अवांछित शाखाओं को मर्ज बेस फिल्टर के उपयोग के लिए धन्यवाद।

#!/bin/bash

file=$1
base=${2:-master}

b=$(tput bold) # Pretty print
n=$(tput sgr0)

echo "Searching for branches with changes to $file related to the $base branch"

# We look through all the local branches using plumbing
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
  # We're establishing a shared ancestor between base and branch, to only find forward changes.  
  merge_base=$(git merge-base $base $branch)
  # Check if there are any changes in a given path.
  changes=$(git diff $merge_base..$branch --stat -- $file)

  if [[ ! -z $changes ]]; then
    echo "Branch: ${b}$branch${n} | Merge Base: $merge_base"
    # Show change statistics pretty formatted
    git diff $merge_base..$branch --stat -- $file
  fi
done

यदि आप इसे git-find-changes(निष्पादन योग्य अनुमतियों के साथ) PATH में डालते हैं - तो आप इसके साथ कॉल कर सकते हैंgit find-changes /path

उदाहरण के लिए आउटपुट git find-changes app/models/

Branch: update_callbacks | Merge base: db07d23b5d9600d88ba0864aca8fe79aad14e55b
 app/models/api/callback_config.rb | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
Branch: repackaging | Merge base: 76578b9b7ee373fbe541a9e39cf93cf5ff150c73
 app/models/order.rb                 | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

बहुत दिलचस्प स्क्रिप्ट। Upvoted। क्या यह शो-चेंज है या बदलाव है?
VonC

@VonC धन्यवाद, सही उपयोग, हर जगह पाया जाना चाहिए
Marcin Raczkowski

0

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

for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
    git checkout $branch && git grep SOMETHING
done

1
क्योंकि यदि आप उस बदलाव को जानते हैं जो आप उपयोग कर सकते हैंgit log -S
सेठ रॉबर्टसन

आप किस खोल को मान रहे हैं? दे घुमा के?
पीटर मोर्टेंसन

कोई बशीज़ नहीं, जो POSIX पर काम करे। मुझे यकीन नहीं है कि for-each-refअभी भी उस shortझंडे का सम्मान करता है । उस ने कहा, मेरे उत्तर की उपेक्षा करो; अन्य उत्तर बेहतर हैं।
व्हाइटिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.