Git दूरस्थ prune, git prune, git fetch --prune, आदि के बीच क्या अंतर हैं


358

मेरी स्थिति यह है ... उसी रेपो पर काम करने वाले किसी व्यक्ति ने अपने स्थानीय और दूरस्थ रेपो से एक शाखा को हटा दिया है ...

अधिकांश लोग जिन्होंने स्टैक ओवरफ्लो या अन्य साइटों पर इस तरह की समस्या के बारे में पूछा है, उनके पास अभी भी शाखा के मुद्दे हैं git branch -aजो नीचे दी गई उनकी दूरस्थ ट्रैकिंग शाखा सूची में दिखाई दे रहे हैं :

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted

हालाँकि, मेरी स्थिति में वह शाखा जो वहाँ नहीं होनी चाहिए, स्थानीय है:

* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah

जब मैं निम्नलिखित में से कोई करता हूं, तो यह स्थानीय रूप से हटाया नहीं जाता है:

$ git prune

मैंने भी कोशिश की:

$ git remote prune origin
$ git fetch --prune

अधिक उपयोगी जानकारी: जब मैं git remote show originदेखता हूं कि यह कैसा है:

* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push  URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
 master                        tracked
 develop                       tracked
 feature_blah                  tracked
 other123                      tracked
 other444                      tracked
 other999                      tracked
Local branches configured for 'git pull':
 develop                      merges with remote develop
 feature_blah                 merges with remote other999
 master                       merges with remote master
 random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for 'git push':
 develop         pushes to develop     (local out of date)
 master          pushes to master      (up to date)
 feature_blah    pushes to feature_blah(up to date)

ध्यान दें कि यह केवल शीर्षक वाले अनुभाग में है Local branches configured for 'git pull':

क्यों?


git branch -d the_local_branch
krsteeve

1
धन्यवाद, लेकिन मैं बस उत्सुक हूं कि ऐसा क्यों हुआ।
गोगोगैडजीनटर्नट

शाखा पदानुक्रम ( x/y) के साथ काम करते समय एक सूक्ष्म अंतर था : इसे ठीक कर दिया गया है ( नीचे मेरा उत्तर देखें )
VonC

जवाबों:


664

मैं आपको इस बारे में निराश होने के लिए दोषी नहीं ठहराता। यह देखने का सबसे अच्छा तरीका है। हर दूरस्थ शाखा के संभावित तीन संस्करण हैं:

  1. रिमोट रिपॉजिटरी पर वास्तविक शाखा
    (जैसे, रिमोट रेपो पर https://example.com/repo.git , refs/heads/master)
  2. स्थानीय रूप से उस शाखा का आपका स्नैपशॉट (नीचे संग्रहीत) है refs/remotes/... )
    (जैसे, स्थानीय रेपो refs/remotes/origin/master)
  3. और एक स्थानीय शाखा जो दूरस्थ शाखा पर नज़र रख सकती है
    (जैसे, स्थानीय रेपो refs/heads/master)

के साथ शुरू करते हैं git prune। यह उन वस्तुओं को हटा देता है जिन्हें अब संदर्भित नहीं किया जा रहा है, यह संदर्भों को नहीं हटाता है। आपके मामले में, आपके पास एक स्थानीय शाखा है। इसका मतलब है कि एक रेफरी नाम है random_branch_I_want_deletedजो कुछ वस्तुओं को संदर्भित करता है जो उस शाखा के इतिहास का प्रतिनिधित्व करते हैं। तो, परिभाषा से, git pruneनहीं हटाएगा random_branch_I_want_deleted। वास्तव में, git pruneGit में जमा हुए डेटा को हटाने का एक तरीका है , लेकिन किसी भी चीज़ से संदर्भित नहीं किया जा रहा है। सामान्य तौर पर, यह किसी भी शाखा के आपके विचार को प्रभावित नहीं करता है।

git remote prune originऔर git fetch --pruneदोनों संदर्भों पर काम करते हैं refs/remotes/...(मैं दूरस्थ संदर्भों के रूप में इनका संदर्भ लूंगा)। यह स्थानीय शाखाओं को प्रभावित नहीं करता है। git remoteअगर आप केवल किसी विशेष दूरदराज के तहत दूरदराज के संदर्भ निकालना चाहते संस्करण उपयोगी है। अन्यथा, दोनों एक ही काम करते हैं। तो, संक्षेप में,git remote prune और git fetch --pruneऊपर 2 नंबर पर काम करते हैं। उदाहरण के लिए, यदि आपने git web GUI का उपयोग करके एक शाखा को हटा दिया है और यह नहीं चाहते हैं कि यह आपकी स्थानीय शाखा सूची ( git branch -r) में दिखाई दे, तो यह वह कमांड है जिसका आपको उपयोग करना चाहिए।

एक स्थानीय शाखा को हटाने के लिए, आपको उपयोग करना चाहिए git branch -d(या -Dयदि यह कहीं भी विलय नहीं हुआ है)। FWIW, दूरस्थ ट्रैकिंग गायब होने पर स्थानीय ट्रैकिंग शाखाओं को स्वचालित रूप से हटाने के लिए कोई git कमांड नहीं है।


22
यह प्रासंगिक मतभेदों को समझाकर समग्र प्रश्न को संबोधित करने का बेहतर काम करता है। यह अतिरिक्त प्रश्नों का भी उत्तर देता है जो मैंने ऊपर दिए थे।
गोगोगैडिनटर्नटेनट

14
यह कमांड उन सभी स्थानीय शाखाओं की एक सूची दिखाएगी जिनके पास एक समान दूरस्थ शाखा नहीं है। आप इसे पाइप कर सकते हैंxargs git branch -D , लेकिन ध्यान दें कि आपके द्वारा बनाई गई कोई भी नई शाखाएं, लेकिन सर्वर से कभी भी नहीं हटाई जाएंगी, इसलिए सावधानी से चलें: git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}'
जेसन वाल्टन

4
@ यह नहीं है। :-( यह केवल स्थानीय रिमोट ट्रैकिंग रेफरी को हटाता है। मैंने इसे
2.7.0

1
@ BlueRaja-DannyPflughoeft उस दृष्टिकोण से सावधान रहें। उदाहरण के लिए, आप अपनी स्थिर शाखाओं को कैसे करते हैं, इसके आधार पर, वे मास्टर शाखा में विलय हो सकते हैं, और आप उन्हें हटा देंगे। यह एक बड़ा नुकसान नहीं है क्योंकि आप उन्हें सर्वर से नहीं हटा रहे हैं, लेकिन यदि आपके पास इसके लिए कोई विशेष कॉन्फ़िगरेशन सेट है, तो वह शाखा खो जाने पर खो जाएगा।
जॉन स्ज़कमेस्टर

1
@ पूरी तरह से सच नहीं है। संदर्भों को पैक किया जा सकता है ( क्षेत्र packed-refsमें फ़ाइल देखें .git), इसलिए जरूरी नहीं कि फ़ाइल एक्सप्लोरर के माध्यम से उन्हें हटाने का एक साधारण मामला हो। यह सुनिश्चित करने के लिए कि दोनों सही ढंग से देखभाल किए गए हैं, कमांड का उपयोग करने के लिए बेहतर है।
जॉन स्ज़ेकमिस्टर

55

git remote pruneऔर git fetch --pruneएक ही काम करें: उन शाखाओं को रेफ्स हटाना जो रिमोट पर मौजूद नहीं हैं, जैसा कि आपने कहा। दूसरी कमांड रिमोट से कनेक्ट होती है और प्रूनिंग से पहले अपनी वर्तमान शाखाओं को लाती है।

हालाँकि, यह आपके द्वारा चेक की गई स्थानीय शाखाओं को नहीं छूता है, जिन्हें आप बस हटा सकते हैं

git branch -d  random_branch_I_want_deleted

बदलें -dद्वारा -Dयदि शाखा कहीं और विलय नहीं किया जाता

git prune कुछ अलग करता है, यह अगम्य वस्तुओं को शुद्ध करता है, उन लोगों को करता है जो किसी भी शाखा या टैग में उपलब्ध नहीं हैं, और इस तरह अब और ज़रूरत नहीं है।


1
मुझे पता है कि यह स्पष्ट लगता है, लेकिन git pruneन केवल शाखाओं और टैग्स के लिए दिखता है, बल्कि अन्य सभी रीफ्स भी।

तो मेरे मामले में, क्यों prune काम नहीं करेगा? क्योंकि यह स्थानीय शाखाओं, लेकिन दूरस्थ संदर्भों की परवाह नहीं करता है? संक्षिप्त जानकारी के लिए धन्यवाद।
गोगोगैडिनटर्नटेट

@hvd ब्रांच और टैग के अलावा किस तरह के रेफ हैं?
चार्ल्सबॉव

@gogogadgetinternet हां बिल्कुल। (आप का मतलब है git remote prune)
चार्ल्सब

4
IMO, ऑब्जेक्ट-कलेक्शन और रेफरेंस-क्लीनअप दोनों के लिए "प्रून" का उपयोग करने का git नामकरण कन्वेंशन है, जहां भ्रम की स्थिति बनी रहती है। लेकिन यह git में कई UI पज़ल में से एक है। :-)
torek

14

इस घटना में कि किसी को भी दिलचस्पी होगी। यहां एक त्वरित शेल स्क्रिप्ट है जो सभी स्थानीय शाखाओं को हटा देगा जो कि दूरस्थ रूप से ट्रैक नहीं किए जाते हैं। सतर्कता का एक शब्द: इससे किसी भी शाखा से छुटकारा मिल जाएगा जो दूर से ट्रैक नहीं किया गया था चाहे वह विलय हो या नहीं।

अगर आप लोगों को इसके साथ कोई समस्या दिखाई देती है तो कृपया मुझे बताएं और मैं इसे ठीक कर दूंगा (आदि)

नामक फाइल में इसे सेव करें git-rm-ntb(इसे कॉल करें जो भी हो) PATHऔर रन करें:

git-rm-ntb <remote1:optional> <remote2:optional> ...

clean()
{
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  RBRANCHES=()
  while read REMOTE; do
    CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "\033[32m Keeping $i \033[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
  done
}

clean $@

धन्यवाद! रंगीन आउटपुट के साथ अच्छा स्पर्श ;-)
बीवेरेंजोव

2
क्या $ (git शाखा -d $ i) केवल विलीन शाखाओं को हटाने के लिए सुरक्षित नहीं होगी?
user2012677

इतना मददगार बहुत बहुत धन्यवाद !!!
रॉबिन हार्टलैंड

सुरक्षित विकल्पों पर चर्चा की जाती है stackoverflow.com/questions/7726949/…
माइकल फ्रीजिम

13

ध्यान दें कि दोनों के बीच एक अंतर git remote --pruneऔर git fetch --pruneसाथ तय की जा रही है, 10a6cc8 प्रतिबद्ध , द्वारा टॉम मिलर ( tmiller) (Git 1.9 / 2.0, Q1 2014):

जब हमारे पास एक रिमोट-ट्रैकिंग शाखा होती है, जिसका नाम frotz/nitfolपिछले भ्रूण से " " होता है, और अपस्ट्रीम में अब "** फ्रॉत्ज़ " ** नाम की एक शाखा होती है , जो अपस्ट्रीम से " " fetchको हटाने में विफल होगी । git समस्या को ठीक करने के लिए उपयोगकर्ता को " " प्रयोग करने के लिए सूचित करेगा ।frotz/nitfolgit fetch --prune
git remote prune

इसलिए: जब एक अपस्ट्रीम रेपो में एक शाखा ("फ्रॉत्ज़") होती है, जिसका नाम एक शाखा पदानुक्रम के रूप में होता है ("फ्रॉत्ज़ / एक्सएक्सएक्स", एक संभावित शाखा नामकरण सम्मेलन ), git remote --pruneतो सफल रहा था (आपके रेपो से दूरस्थ शाखा को साफ करने में) , लेकिन git fetch --pruneअसफल हो रहा था।

अब और नहीं:

जिस तरह से " fetch --prune" काम करता है, वह प्रचलित ऑपरेशन को आगे बढ़ाने से पहले करें।
इस तरह, एक संघर्ष के उपयोगकर्ता को चेतावनी देने के बजाय, यह स्वचालित रूप से इसे ठीक करता है।

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