Git शाखा के निकटतम जनक कैसे खोजें?


419

मान लें कि मेरे पास इस तरह के एक प्रतिबद्ध पेड़ के साथ निम्नलिखित स्थानीय भंडार हैं:

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

masterयह मेरा नवीनतम स्थिर रिलीज़ कोड है , क्या developयह मेरा 'अगला' रिलीज़ कोड है , और इसके featureलिए एक नई सुविधा तैयार की जा रही हैdevelop

क्या मैं हुक का उपयोग करके अपने रिमोट रेपो पर सक्षम होना चाहता हूं, featureजब तक कि fवह developHEAD का प्रत्यक्ष वंशज नहीं है, तब तक धकेलने से इनकार कर दिया जाएगा । यानी कमिट ट्री ऐसा दिखता है क्योंकि फीचर git rebaseचालू है d

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

तो क्या यह संभव है:

  • की मूल शाखा को पहचानें feature?
  • मूल शाखा में उस कमेटी की पहचान करें, जिसका fवंशज है?

वहाँ से मैं जाँच करूँगा कि माता-पिता शाखा का HEAD क्या है, और देखें कि क्या fपूर्ववर्ती मूल शाखा HEAD से मेल खाता है, यह निर्धारित करने के लिए कि क्या सुविधा को फिर से चलाने की आवश्यकता है।


यह प्रश्न माता-पिता के माता-पिता को खोजने के लिए फिर से किया जाना चाहिए।
टिम बोलैंड

जवाबों:


347

यह मानते हुए कि दूरस्थ रिपॉजिटरी में विकास की एक प्रति है शाखा (आपका प्रारंभिक विवरण स्थानीय रिपॉजिटरी में इसका वर्णन करता है, लेकिन ऐसा लगता है कि यह रिमोट में भी मौजूद है), आपको वह हासिल करने में सक्षम होना चाहिए जो मुझे लगता है कि आप चाहते हैं, लेकिन दृष्टिकोण आपने जो कल्पना की है, उससे थोड़ा अलग है।

Git का इतिहास कमिट्स के DAG पर आधारित है। शाखाएँ ("सामान्य रूप से") केवल क्षणिक लेबल हैं जो निरंतर बढ़ते हुए DAG में विशिष्ट कमिट की ओर इशारा करती हैं। जैसे, शाखाओं का संबंध समय के साथ अलग-अलग हो सकता है, लेकिन आवागमन के बीच का संबंध नहीं होता है।

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

ऐसा लगता है कि baz(पुराने संस्करण पर) आधारित है bar? लेकिन अगर हम हटा दें तो क्या होगा bar?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

अब ऐसा लग रहा है कि bazयह पर आधारित है foo। लेकिन पूर्वजों में bazबदलाव नहीं हुआ, हमने सिर्फ एक लेबल (और परिणामस्वरूप झूलने की प्रतिबद्धता) को हटा दिया। और क्या होगा अगर हम एक नया लेबल जोड़ते हैं 4?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

अब ऐसा लग रहा है कि bazयह पर आधारित है quux। फिर भी, वंश नहीं बदला, केवल लेबल बदल गए।

यदि, हालांकि, हम पूछ रहे थे "प्रतिबद्ध का 6एक वंशज है 3?" (मानकर 3और 6पूर्ण SHA-1 प्रतिबद्ध नाम हैं), तो उत्तर "हां" होगा, चाहे लेबल barऔर quuxमौजूद हों या नहीं।

तो, आप ऐसे सवाल पूछ सकते हैं जैसे "धक्का दिया गया है कि विकसित शाखा की वर्तमान टिप का एक वंशज है ?", लेकिन आप मज़बूती से नहीं पूछ सकते हैं "धक्का दिया प्रतिबद्ध की मूल शाखा क्या है?"।

एक सबसे विश्वसनीय प्रश्न जो आप चाहते हैं, उसके करीब पहुंचने के लिए लगता है:

सभी पुश किए गए पूर्वजों के लिए ( विकास और उसके पूर्वजों की वर्तमान टिप को छोड़कर ), जिनके पास माता-पिता के रूप में विकसित होने की वर्तमान टिप है :

  • कम से कम एक ऐसी प्रतिबद्धता मौजूद है?
  • क्या सभी ऐसे एकल-अभिभावक कमिट हैं?

जिसे इस प्रकार लागू किया जा सकता है:

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

यह कुछ को कवर करेगा जिसे आप प्रतिबंधित करना चाहते हैं, लेकिन शायद सब कुछ नहीं।

संदर्भ के लिए, यहां एक विस्तारित उदाहरण इतिहास है:

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \   
                        R---S

ऊपर दिए गए कोड को अस्वीकार करने के लिए इस्तेमाल किया जा सकता है Hऔर S, जबकि स्वीकार करने H', J, K, या N, लेकिन यह भी स्वीकार करेंगे Lऔर P(वे आपस में विलय शामिल है, लेकिन वे की नोक आपस में नहीं मिलाते विकसित )।

अस्वीकार करने के लिए Lऔर P, आप प्रश्न को बदल सकते हैं और पूछ सकते हैं

सभी पुश किए गए पूर्वजों के लिए ( विकास और उसके पूर्वजों की वर्तमान टिप को छोड़कर ):

  • क्या दो माता-पिता के साथ कोई विवाद है?
  • यदि नहीं, तो क्या कम से कम एक ऐसे प्रतिबद्ध के पास अपने (केवल) माता-पिता को विकसित करने की वर्तमान टिप है ?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac

मुझे यह मिलता है: git: घातक: अस्पष्ट तर्क '...': संशोधन और फ़ाइल नाम दोनों। ट्रिपल डॉट्स इरादा क्या है?
जैक उलेजा

1
@ श्नाइडर मुझे पूरा यकीन है कि '...' इस उदाहरण में एक प्लेसहोल्डर होने का इरादा है: यदि आप इसे उस एसएचए के साथ प्रतिस्थापित करते हैं जो आप इस चेक के खिलाफ प्रदर्शन करने की कोशिश कर रहे हैं (कहते हैं, शाखा के हेड आप वर्तमान में हैं), सब कुछ ठीक काम करता है।
डैनियल ब्रैडी 23

इस विस्तृत उत्तर के लिए धन्यवाद! यह सुपर उपयोगी है। मैं एक समान हुक बनाना चाहता हूं, लेकिन मैं विकास शाखा के नाम को हार्ड-कोड नहीं करना चाहता। मतलब मैं मूल शाखा के अलावा किसी शाखा को छूट देने से रोकने के लिए हुक चाहता हूं। अगर मुझे आपका उत्तर अच्छी तरह से समझ में आ रहा है (मैं बैश और सामान के लिए नया हूँ) तो यह आपके उत्तर में शामिल नहीं है, है ना? क्या इसे करने का कोई तरीका है?
केमिया

क्या आप संबंधित प्रश्न का उत्तर देने के लिए तैयार हैं? मैं REMOTE रिपॉजिटरी पर काम करने के लिए आपका कोड प्राप्त करने में सक्षम नहीं था। यहाँ एक REMOTE रिपॉजिटरी के साथ काम करने के लिए अपने दृष्टिकोण को कैसे अनुकूलित किया जाए, इसके बारे में फॉलो-अप प्रश्न का लिंक है: stackoverflow.com/questions/49619492/…
CodeMed

जब मेरे पास यह काम नहीं करता था develop > release > feature, तो मैं वापस विकसित हो जाता था और इसे माता-पिता को जानने की आवश्यकता होती थी। मेरी समस्या का समाधान था stackoverflow.com/a/56673640/2366390
verdverm

240

एक रेफरल

प्रश्न को वाक्यांश करने का एक अन्य तरीका यह है कि "वर्तमान शाखा के अलावा किसी शाखा पर रहने वाला निकटतम वचन क्या है, और वह कौन सी शाखा है?"

एक तरकीब

आप इसे थोड़ा सा कमांड लाइन मैजिक के साथ पा सकते हैं

git show-branch \
| sed "s/].*//" \
| grep "\*" \
| grep -v "$(git rev-parse --abbrev-ref HEAD)" \
| head -n1 \
| sed "s/^.*\[//" 

Awk के साथ :

git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \
| awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'

यहां देखिए यह कैसे काम करता है:

  1. दूरस्थ शाखाओं सहित सभी कमिट्स का एक पाठ्य इतिहास प्रदर्शित करें।
  2. वर्तमान प्रतिबद्ध के पूर्वजों को एक स्टार द्वारा इंगित किया जाता है। बाकी सब कुछ छान लें।
  3. वर्तमान शाखा में सभी कमिट्स को अनदेखा करें।
  4. पहला परिणाम निकटतम पूर्वजों की शाखा होगा। अन्य परिणामों पर ध्यान न दें।
  5. शाखा नाम [कोष्ठक में] प्रदर्शित होते हैं। कोष्ठक, और कोष्ठक के बाहर सब कुछ अनदेखा करें।
  6. कभी-कभी शाखा के नाम में उल्लिखित प्रतिबद्ध और शाखा टिप के बीच कितने कमिट होते हैं, यह बताने के लिए एक ~ # या ^ # शामिल होगा। हम परवाह नहीं करते। उन पर ध्यान न दें।

और परिणाम

उपरोक्त कोड को चालू करना

 A---B---D <-master
      \
       \
        C---E---I <-develop
             \
              \
               F---G---H <-topic

developयदि आप इसे H से चलाते हैं और masterयदि आप इसे I से चलाते हैं तो आपको दे देंगे ।

कोड एक जिस्ट के रूप में उपलब्ध है


24
त्रुटि के कारण एक अनुगामी backtick निकाल दिया। हालांकि इस आदेश को चलाने के दौरान, मुझे बड़ी मात्रा में चेतावनी मिलती है, प्रत्येक शाखा के बारे में शिकायत करते हुए कहते हैंcannot handle more than 25 refs
जॉन एल।

1
@JoeChrysler क्या आपको लगता है कि आप इसे 2 के बजाय एक पंक्ति बना सकते हैं, और संभवतः मैक पर यह काम कर सकते हैं जैसा ackकि मैक पर उपलब्ध नहीं है (किसी ने ackसाथ बदलने का सुझाव दिया है grep)
nonopolarity

53
क्षमा करें, यह एक गलत है। यहाँ सही है कि मेरे लिए काम किया है:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot

15
@droidbot नाइस, लेकिन जब grep -v कैच मैसेज या आपके ब्रांच का नाम किसी दूसरे ब्रांच नेम का हिस्सा हो, तो refs को हटाने से बचने के लिए पाइपिंग रीऑर्डरिंग की जरूरत होती है। git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
गालू जूल

3
@OlegAbrazhaev मुझे नहीं पता कि क्या तुमने कभी अपने सवाल का जवाब दिया। के git उपनाम का उपयोग करना: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"मेरे लिए काम करता है
mduttondev

111

आप भी आजमा सकते हैं:

git log --graph --decorate

5
git log --graph --decorate --simplify-by-decoration--graphवैकल्पिक कहां है
Na13-c

1
git log --graph --decorate --simplify-by-decoration --oneline
ऐश्वर्या ४

106

जनक जनक

आप बस कमांड चला सकते हैं

git parent

शाखा के माता-पिता को खोजने के लिए, यदि आप @ उर्फ क्रिसलर के उत्तर को एक उपनाम के रूप में जोड़ते हैं । यह उपयोग को सरल करेगा।

"~/.gitconfig"किसी भी पाठ संपादक का उपयोग करके स्थित gitconfig फ़ाइल खोलें । (Linux के लिए)। और विंडोज के लिए ".gitconfig" पथ आमतौर पर स्थित हैc:\users\your-user\.gitconfig

vim  ~/.gitconfig

फ़ाइल में निम्न उपनाम आदेश जोड़ें:

[alias]
            parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"

सहेजें और संपादक से बाहर निकलें।

कमांड चलाएं git parent

बस!


5
यह एक बेहतरीन उपाय है। अपेक्षित परिणामों के प्रति आश्वस्त होने के लिए कुछ नमूना आउटपुट को जोड़ना भी उपयोगी होगा। जब मैंने इसे चलाया, तो मुझे बहुत अंतिम पंक्ति से पहले कुछ चेतावनी मिली, जो मुझे विश्वास है कि मूल शाखा का नाम था।
ttemple

4
एक जादू की तरह काम करता है! विंडोज़ उपयोगकर्ताओं के लिए .gitconfig आम तौर पर c: \ users \ your-user \। .conconfig
zion

12
cannot handle more than 25 refsअपवाद हो रहा है।
शगुन

किसी को चेतावनी को संभालने के लिए संपादित कर सकते हैं? @ttemple, आप कर सकते हैं?
NIKHIL CM

@NIKHILCM एक चैंपियन की तरह काम करता है। लेकिन मेरा यहाँ पर एक सवाल है कि क्या अभिभावक इंगित करता है कि शाखा कहाँ से बनी या कुछ और?
हरिप्रसाद

52

मेरे पास आपकी समग्र समस्या का समाधान है (यह निर्धारित करें कि featureक्या टिप से नीचे उतरा है develop), लेकिन यह आपके द्वारा उल्लिखित विधि का उपयोग करके काम नहीं करता है।

आप git branch --containsकी नोक से उतरी सभी शाखाओं को सूचीबद्ध करने के लिए उपयोग कर सकते हैं develop, फिर grepयह सुनिश्चित करने के लिए उपयोग करें कि featureउनमें से क्या है।

git branch --contains develop | grep "^ *feature$"

यदि यह उनके बीच है, तो यह " feature"मानक आउटपुट पर प्रिंट होगा और 0. का रिटर्न कोड होगा। अन्यथा, यह कुछ भी नहीं प्रिंट करेगा और 1 का रिटर्न कोड होगा।


1
यह काम करता है लेकिन यह ध्यान दिया जाना चाहिए कि यह एक भंडार पर लंबे समय तक ले सकता है जिसमें बहुत सारे रेफ हैं। यह इसे चलाने के लिए आदर्श से थोड़ा कम बनाता है, उदाहरण के लिए, एक पूर्व-प्राप्त हुक।
Ebneter

मैं शाखा की तलाश में था, हम इसे कॉल करेंगे <branch>, जहां मैंने प्रदर्शन किया: git checkout -b <branch-2>से ... यह जवाब है! वास्तव में, grep की कोई आवश्यकता नहीं है। git branch --contains <branch>
पूपी McFartnoise

44

यह मेरे लिए ठीक काम कर रहा है।

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

सौजन्य से जवाब: @droidbot और @Jistanidiot


हाँ, लेकिन कभी-कभी यह आपको ग्रीप से "टूटी हुई पाइप" मिलता है।
व्लादिस्लाव रास्ट्रुस

1
*grep पास करने के लिए एक उचित रेगेक्स नहीं है। उपयोग करना चाहिए grep -F '*'या grep '\*'इसके बजाय। अच्छा समाधान अन्यथा।
arielf

मुझे कोई आउटपुट नहीं मिला।
संदीप सुबेदी

मेरे लिए काम करता है ....
roottraveller

11

चूँकि उपरोक्त उत्तर में से कोई भी हमारे रिपॉजिटरी पर काम नहीं करता है, मैं अपने तरीके से साझा करना चाहता हूं, जिसमें नवीनतम मर्ज का उपयोग कर रहा हूं git log:

#!/bin/bash
git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 10

इसे एक स्क्रिप्ट नाम में रखें git-last-merges, जो एक शाखा का नाम तर्क (वर्तमान शाखा के बजाय) के साथ-साथ अन्य git logतर्कों को भी स्वीकार करता है

आउटपुट से, हम स्वयं शाखा शाखा और प्रत्येक शाखा से विलय की संख्या के आधार पर मूल शाखा का पता लगा सकते हैं।

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

#!/bin/bash
HEAD="`git rev-parse --abbrev-ref HEAD`"
echo "Comparing to $HEAD"
printf "%12s  %12s   %10s     %s\n" "Behind" "BehindMerge" "Ahead" "Branch"
git branch | grep -v '^*' | sed 's/^\* //g' | while read branch ; do
    ahead_merge_count=`git log --oneline --merges $branch ^$HEAD | wc -l`
    if [[ $ahead_merge_count != 0 ]] ; then
        continue
    fi
    ahead_count=`git log --oneline --no-merges $branch ^$HEAD | wc -l`
    behind_count=`git log --oneline --no-merges ^$branch $HEAD | wc -l`
    behind_merge_count=`git log --oneline --merges ^$branch $HEAD | wc -l`
    behind="-$behind_count"
    behind_merge="-M$behind_merge_count"
    ahead="+$ahead_count"
    printf "%12s  %12s   %10s     %s\n" "$behind" "$behind_merge" "$ahead" "$branch"
done | sort -n

धन्यवाद। हालांकि यह बहुत अच्छा काम नहीं कर सकता है यदि आप rebaseअक्सर उपयोग करते हैं (और विलय fast-forwardअक्सर एड होते हैं)। अगर मुझे बेहतर हल मिल गया तो मैं अपना जवाब संपादित करूँगा।
सईदग्नू

1
केवल? अब तक का जवाब जिसने वर्तमान शाखा के मास्टर होने के मामले में मेरे लिए समझदारी से काम लिया। अधिकांश अन्य समाधानों ने एक यादृच्छिक रूप से (और स्पष्ट रूप से गलत) परिणाम दिया, जो कि वास्तव में मूल अभिभावक शाखाएं नहीं हैं।
18:09

यह एकमात्र उत्तर है जिसने मेरे लिए काम किया। पहले 10 की सूची के बजाय पहला अभिभावक प्राप्त करने के लिए आप इसका उपयोग कर सकते हैं: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
सारे जूल

10

एक तरकीब

समाधान के आधार परgit show-branch तो मैं एक से संयोजित कर दी है, काफी मुझे (नीचे देखें) के लिए काम करते नहीं था के आधार परgit log और इस के साथ समाप्त हो गया:

git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
      | grep -v "(HEAD" \                               # removes current head (and branch)
      | head -n1 \                                      # selects only the closest decoration
      | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
      | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
      | sed 's/origin\///'                              # strips "origin/" from the decoration

मर्यादा और कैवियट

  • HEAD को अलग किया जा सकता है (कई CI उपकरण ऐसा करने के लिए सुनिश्चित करते हैं कि वे किसी दिए गए शाखा में सही कमिटमेंट का निर्माण करते हैं), लेकिन मूल शाखा और स्थानीय शाखा को वर्तमान HEAD के बराबर या " दोनों " बराबर होना चाहिए ।
  • रास्ते में कोई टैग नहीं होना चाहिए (मैं अनुमान लगाता हूं; मैंने बच्चे और माता-पिता की शाखा के बीच टैग के साथ कमिट पर स्क्रिप्ट का परीक्षण नहीं किया है)
  • स्क्रिप्ट इस तथ्य पर निर्भर करती है कि "हेड" को हमेशा कमांड द्वारा पहली सजावट के रूप में सूचीबद्ध किया जाता हैlog
  • पर masterऔरdevelop परिणाम (ज्यादातर) में स्क्रिप्ट चल रहा है<SHA> Initial commit

परिणाम

 A---B---D---E---F <-origin/master, master
      \      \
       \      \
        \      G---H---I <- origin/hotfix, hotfix
         \
          \
           J---K---L <-origin/develop, develop
                \
                 \
                  M---N---O <-origin/feature/a, feature/a
                       \   \
                        \   \
                         \   P---Q---R <-origin/feature/b, feature/b
                          \
                           \
                            S---T---U <-origin/feature/c, feature/c

स्थानीय शाखा अस्तित्व के बावजूद (जैसे कि केवल तब origin/topicसे मौजूद है, जब Oउसके एसएचए द्वारा सीधे जांच की गई थी), स्क्रिप्ट को निम्नानुसार प्रिंट करना चाहिए:

  • प्रतिबद्ध के लिए G, H,I (शाखा hotfix) →master
  • प्रतिबद्ध के लिए M, N,O (शाखा feature/a) →develop
  • प्रतिबद्ध के लिए S, T,U (शाखा feature/c) →develop
  • प्रतिबद्ध के लिए P, Q,R (शाखा feature/b) →feature/a
  • प्रतिबद्ध के लिए J, K, L(शाखा develop) → <sha> Initial commit*
  • प्रतिबद्ध के लिए B, D, E, F(शाखा master) →<sha> Initial commit

* - या masterयदि developमास्टर के हेड के ऊपर कमिट्स थे (~ मास्टर को विकसित करने के लिए तेजी से अग्रेषित किया जाएगा)


मेरे लिए शो-ब्रांच का काम क्यों नहीं हुआ

समाधान के आधार परgit show-branch निम्न परिस्थितियों में मेरे लिए अविश्वसनीय साबित कर दिया:

  • अलग सिर - अलग सिर मामले सहित जगह का मतलब हैgrep '\*' \ `क्रेप 'के लिए !' \ - और वह सिर्फ सभी परेशानियों की शुरुआत है
  • चल स्क्रिप्ट पर masterऔरdevelop में परिणाम developक्रमशः और ``
  • शाखाओं परmaster शाखाएं ( hotfix/शाखाएं) developएक माता-पिता के रूप में समाप्त होती हैं क्योंकि उनके निकटतम masterशाखा माता-पिता को एक कारण के !बजाय चिह्नित किया गया था *

2
केवल उत्तर दें कि काम किया है - एक गित उर्फ ​​के रूप में:"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
इयान केम्प

8

याद रखें कि, जैसा कि "गिट: वर्णित है कि किस शाखा से एक प्रतिबद्ध आया था" , आप आसानी से उस शाखा को इंगित नहीं कर सकते हैं जहां वह कमिट किया गया है (शाखाओं का नाम बदला जा सकता है, स्थानांतरित किया जा सकता है, हटा दिया गया है ...), भले ही git branch --contains <commit>एक शुरुआत है।

  • आप शाखा और सूची शाखा को सूचीबद्ध git branch --contains <commit>नहीं करने तक प्रतिबद्ध से वापस जा सकते हैं ,featuredevelop
  • तुलना करें कि SHA1 को प्रतिबद्ध करें /refs/heads/develop

यदि दो आईडी मिलान करता है, तो आप जाने के लिए अच्छा है (इसका मतलब है कि featureशाखा का मूल आधार है develop)।


6

जो क्रिसलर की कमांड-लाइन जादू को सरल बनाया जा सकता है। यहाँ जो तर्क दिया गया है - संक्षिप्तता के लिए मैंने दोनों संस्करणों में cur_branchकमांड प्रतिस्थापन के स्थान पर नामित पैरामीटर पेश किया है `git rev-parse --abbrev-ref HEAD`; इसे ऐसे शुरू किया जा सकता है:

cur_branch=$(git rev-parse --abbrev-ref HEAD)

फिर, यहाँ है जो पाइपलाइन:

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

हम एक ही सरल awkकमांड में उन सभी व्यक्तिगत फिल्टर के पांच के रूप में एक ही चीज को पूरा कर सकते हैं :

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'  

यह इस तरह टूट जाता है:

-F'[]^~[]' 

पर खेतों में लाइन विभाजित ], ^, ~, और [अक्षर।

/\*/                      

उन पंक्तियों को खोजें जिनमें एक तारांकन हो

&& !/'"$cur_branch"'/

... लेकिन वर्तमान शाखा का नाम नहीं

{ print $2;               

जब आप इस तरह की लाइन पाते हैं, तो इसके दूसरे क्षेत्र को प्रिंट करें (यानी, हमारे क्षेत्र विभाजक वर्णों की पहली और दूसरी घटनाओं के बीच का हिस्सा)। सरल शाखा नामों के लिए, बस वही होगा जो कोष्ठक के बीच है; रिश्तेदार छलांग के साथ refs के लिए, यह सिर्फ संशोधक के बिना नाम होगा। इसलिए क्षेत्र विभाजकों का हमारा सेट दोनों sedकमांड के इरादे को संभालता है ।

  exit }

फिर तुरंत बाहर निकलें। इसका मतलब है कि यह केवल पहली मिलान रेखा को संसाधित करता है, इसलिए हमें आउटपुट को पाइप करने की आवश्यकता नहीं है head -n 1


3
ध्यान दें कि बहुत अधिक रेफ के कारण कुछ शाखाएँ आउटपुट से गायब हो सकती हैं। उन्हें इसके बजाय स्टॉडर पर चेतावनी के रूप में दिखाया गया है।
Zitrax

5

यहाँ मार्क रीड के समाधान का पावरशेल कार्यान्वयन है:

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }

5

मैं यह नहीं कह रहा हूं कि यह इस समस्या को हल करने का एक अच्छा तरीका है, हालांकि यह मुझे काम के लिए लगता है।

git branch --contains $(cat .git/ORIG_HEAD) मुद्दा यह है कि किसी फ़ाइल को कैटिट किया जा रहा है, यह git के आंतरिक कार्य में झाँक रहा है, इसलिए यह आवश्यक रूप से फॉरवर्ड-संगत (या पीछे की ओर संगत) नहीं है।


3

चींटी के साथ क्रॉस-प्लेटफॉर्म कार्यान्वयन

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />

2

@ मर्क रीड: आपको यह जोड़ना चाहिए कि कमिट लाइन में न केवल तारांकन होना चाहिए, बल्कि एक तारांकन के साथ शुरू होना चाहिए! अन्यथा ऐसे संदेश जो एक तारांकित होते हैं, वे भी मेल खाती लाइनों में शामिल होते हैं। तो यह होना चाहिए:

git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'

या लंबा संस्करण:

git show-branch -a           |
  awk '^\*'                  | # we want only lines that contain an asterisk
  awk -v "$current_branch"   | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed`

2
vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

मार्क रीड के जवाब के समान ही प्राप्त होता है, लेकिन बहुत अधिक सुरक्षित दृष्टिकोण का उपयोग करता है जो कई परिदृश्यों में दुर्व्यवहार नहीं करता है:

  1. पेरेंट ब्रांच की अंतिम प्रतिबद्धता एक मर्ज है, जिससे कॉलम शो - नहीं होता है*
  2. प्रतिबद्ध संदेश में शाखा का नाम होता है
  3. प्रतिबद्ध संदेश शामिल हैं *

0

इन दिनों ऐसा करने के इच्छुक कोई भी व्यक्ति - एटलसियन के सोर्सट्री एप्लिकेशन से आपको पता चलता है कि आपकी शाखाएं एक-दूसरे से कैसे संबंधित हैं, यानी जहां वे शुरू हुई थीं और जहां वे वर्तमान में प्रतिबद्ध क्रम में बैठती हैं (जैसे HEAD या 4 पीछे बैठती हैं, इत्यादि) का एक शानदार दृश्य प्रतिनिधित्व करता है। ।


0

यदि आप स्रोत वृक्ष का उपयोग अपने प्रतिबद्ध विवरण> माता-पिता> पर करते हैं, तो आप प्रतिबद्ध संख्याओं को रेखांकित (लिंक) देखेंगे


0

एक विकल्प: git rev-list master | grep "$(git rev-list HEAD)" | head -1

अंतिम वचन लें कि यह मेरी शाखा है और master(या जो भी शाखा आप निर्दिष्ट करना चाहते हैं)


0

यह मेरे लिए काम नहीं करता था जब मैंने कुछ ऐसा किया था develop > release-v1.0.0 > feature-foo, तो यह सभी तरह से वापस विकसित होगा, ध्यान दें इसमें एक रिबेस शामिल था, निश्चित नहीं कि अगर यह मेरे मुद्दे को कम कर रहा है ...

निम्नलिखित ने मेरे लिए सही प्रतिबद्ध हैश दिया

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.