डिफ़ॉल्ट रूप से तेजी से आगे विलय क्यों होता है?


641

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

मैंने git का उपयोग करके अपना नया प्रोजेक्ट शुरू किया और अपनी पहली सुविधा समाप्त की। सुविधा को मर्ज करते समय, मुझे एहसास हुआ कि git तेज-फॉरवर्ड का उपयोग करता है, अर्थात यह मेरे परिवर्तन को सीधे मास्टर शाखा में लागू करता है यदि संभव हो तो और मेरी शाखा को भूल जाता है।

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

इस तर्क से, मैं तेज-अग्रेषित विलय नहीं चाहता और यह नहीं देख सकता कि यह डिफ़ॉल्ट क्यों है। इसके बारे में क्या अच्छा है?


38
नोट: यह भी देखें sandofsky.com/blog/git-workflow.html , और no-ffइसके "चेकपॉइंट कमिट्स" से बचें जो बिस्केट या दोष को तोड़ते हैं।
VonC

15
एक आदमी परियोजना पर git का उपयोग करके क्या आपको खेद है?
हैवगेस

27
बिलकुल नहीं! मेरे कार्य फ़ोल्डर में मेरे पास 7 एक-आदमी परियोजनाएं हैं जहां मैं गिट का उपयोग करता हूं। मुझे यह बताने की ज़रूरत है कि: मैंने यह सवाल पूछने के बाद से कई परियोजनाएँ शुरू कीं और उन सभी को गिट के माध्यम से तैयार किया गया। जहाँ तक मुझे पता है, स्थानीय संस्करण का केवल git और mercurial समर्थन है, जो मेरे लिए आवश्यक है क्योंकि मुझे इसकी आदत हो गई है। इसे स्थापित करना आसान है और आपके पास हमेशा पूरा इतिहास है। समूह की परियोजनाओं में यह और भी बेहतर है, क्योंकि आप अपने कार्य-प्रगति कोड के साथ किसी को भी हस्तक्षेप किए बिना प्रतिबद्ध कर सकते हैं। इसके अलावा मैं अपनी कुछ परियोजनाओं (जैसे माइक्रो-ऑप्टपर्स) को साझा करने के लिए जीथब का उपयोग करता हूं जहां गिट की आवश्यकता होती है।
फ्लोरियन पिल्ज़

7
@ कावा सच, -no-ffशायद ही कभी एक अच्छा विचार है, लेकिन अभी भी मुख्य शाखा पर केवल एक प्रतिबद्ध रिकॉर्डिंग के दौरान एक सुविधा-आंतरिक इतिहास रखने में मदद कर सकता है। यह लंबे फीचर इतिहास के लिए समझ में आता है, जब आप समय-समय पर इसकी प्रगति को मुख्य शाखा में विलय कर देते हैं।
वॉन

12
वैसे, आपके सवाल का "यह नहीं है कि [एक रैखिक शाखा इतिहास] अव्यवसायिक दिखते हैं?"। डिफॉल्ट के साथ सोर्स कोड सिस्टम का उपयोग करने के बारे में कुछ भी अव्यवसायिक नहीं है। यह व्यावसायिकता के बारे में नहीं है। यह यह निर्धारित करने के बारे में है कि आप किस शाखा में आपकी सदस्यता लेते हैं। उदाहरण के लिए, @VonC सैंडोफ़्स्की के लेख से जुड़ा हुआ है जहां वह एक बेहतर दृष्टिकोण के रूप में तेजी से आगे का उपयोग करते हुए चैंपियन बनते हैं। सही या गलत नहीं, विभिन्न संदर्भों के लिए सिर्फ अलग दर्शन।
Marplesoft

जवाबों:


718

फास्ट-फ़ॉरवर्ड मर्जिंग अल्पकालिक शाखाओं के लिए समझ में आता है, लेकिन अधिक जटिल इतिहास में , गैर-फास्ट-फ़ॉरवर्ड मर्जिंग से इतिहास को समझना आसान हो सकता है, और कमिट्स के समूह को वापस करना आसान हो सकता है।

चेतावनी : गैर-फास्ट-फ़ॉरवर्डिंग के संभावित दुष्प्रभाव भी हैं। कृपया https://sandofsky.com/blog/git-workflow.html की समीक्षा करें , इसके "चेकपॉइंट कमिट्स" से बचें जो बिस्केट या दोष को तोड़ते हैं, और ध्यान से विचार करें कि क्या यह आपके लिए डिफ़ॉल्ट दृष्टिकोण होना चाहिए master

वैकल्पिक शब्द
( Nvie.com से , विन्सेन्ट ड्रिसेन , पोस्ट " एक सफल गिट ब्रांचिंग मॉडल ")

विकसित पर एक समाप्त सुविधा को शामिल करना

तैयार सुविधाओं को आगामी रिलीज में जोड़ने के लिए विकसित शाखा में विलय किया जा सकता है:

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

--no-ffझंडा हमेशा बनाने के लिए एक नई वस्तु प्रतिबद्ध मर्ज का कारण बनता है, भले ही मर्ज के साथ तेजी से आगे किया जा सकता है। यह सुविधा शाखा के ऐतिहासिक अस्तित्व के बारे में जानकारी खोने से बचाती है और समूह सभी एक साथ मिलकर यह कहते हैं कि इस सुविधा को जोड़ा।

जकुब नारबस्की ने भी इस विन्यास का उल्लेख किया है :merge.ff

डिफ़ॉल्ट रूप से, Git एक अतिरिक्त मर्ज कमिट नहीं बनाता है जब एक कमेट को मर्ज करता है जो कि वर्तमान कमिट का वंशज है। इसके बजाय, वर्तमान शाखा की नोक तेजी से अग्रेषित की जाती है।
जब सेट किया जाता है false, तो यह वैरिएबल ऐसे मामले में एक अतिरिक्त मर्ज कमिट बनाने के लिए कहता है ( --no-ffकमांड लाइन से विकल्प देने के बराबर )।
जब ' only' पर सेट किया जाता है , तो केवल ऐसे फास्ट-फ़ॉरवर्ड मर्ज को अनुमति दी जाती है ( --ff-onlyकमांड लाइन से विकल्प देने के बराबर )।


फास्ट-फ़ॉरवर्ड डिफ़ॉल्ट है क्योंकि:

  • अल्पकालिक शाखाएं गिट में बनाने और उपयोग करने के लिए बहुत आसान हैं
  • अल्पकालिक शाखाएँ अक्सर कई कमियों को अलग करती हैं जिन्हें उस शाखा के भीतर स्वतंत्र रूप से पुनर्गठित किया जा सकता है
  • वे कमिट वास्तव में मुख्य शाखा का हिस्सा हैं: एक बार पुनर्गठित होने के बाद, मुख्य शाखा उन्हें शामिल करने के लिए तेजी से अग्रसर होती है।

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

इस स्थिति में, आप इस तरह की कॉन्फिग फ़ाइल सेट कर सकते हैं :

[branch "master"]
# This is the list of cmdline options that should be added to git-merge 
# when I merge commits into the master branch.

# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.

# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.

mergeoptions = --no-commit --no-ff

ओपी टिप्पणियों में जोड़ता है:

मैं [अल्पकालिक] शाखाओं के लिए फास्ट फॉरवर्ड में कुछ समझदारी देखता हूं, लेकिन इसे डिफ़ॉल्ट क्रिया बनाने का अर्थ है कि गिट आपको मानता है ... अक्सर [अल्पकालिक] शाखाएं होती हैं। उचित?

जेफ्रोमी जवाब:

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

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

अधिक आम तौर पर, मैं जोड़ता हूं:

यह वास्तव में आपके विकास वर्कफ़्लो पर निर्भर करता है :

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

देखें "आपको कब शाखा लगानी चाहिए? "

वास्तव में, जब आप मर्क्युरियल शाखा मॉडल पर विचार, यह अपने मूल में है एक भंडार प्रति शाखा (भले ही आप बना सकते हैं गुमनाम सिर, बुकमार्क और भी नामित शाखाओं )
देखें "- तुलना करें और कंट्रास्ट Git और मर्क्युरियल"

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


वाह जो तेज था। ;) मुझे पता नहीं है कि -f- एफएफ विकल्प के बारे में, लेकिन मैं अपनी सुविधा के खराब होने के बाद ही फास्ट-फॉरवर्ड के बारे में पता लगाता हूं। मुझे छोटी जीवित शाखाओं के लिए तेजी से आगे बढ़ने में कुछ समझदारी दिखाई देती है, लेकिन इसे डिफ़ॉल्ट क्रिया बनाने का अर्थ है, यह है कि आप सबसे अधिक अक्सर ऐसी छोटी जीवित शाखाएं मानते हैं। उचित?
फ्लोरियन पिल्ज़

@ फ़्लोरियन: मेरा मानना ​​है कि यह प्रक्रिया का एक उचित दृष्टिकोण है। मैंने एक विन्यास का एक उदाहरण जोड़ा है जो उस तरीके को सेटअप करेगा जिसे आप मास्टर में मर्ज करना चाहते हैं।
वॉनसी

धन्यवाद, कॉन्फ़िगर फ़ाइल को ऐसे गोच से बचने में मदद करनी चाहिए। :) केवल इस विन्यास को "git config branch.master.mergeoptions '--no-ff' के साथ स्थानीय रूप से लागू किया गया है
फ्लोरियन पिल्ज़

2
@BehrangSaeedzadeh: रिबासिंग एक अन्य विषय है (जिसका इस पृष्ठ में उल्लेख नहीं किया गया है): जब तक आप अपनी featureशाखा को किसी सार्वजनिक रेपो में धकेल नहीं देते हैं , तब तक आप इसे masterजितनी बार चाहें उतनी बार शीर्ष पर वापस कर सकते हैं। देखें stackoverflow.com/questions/5250817/…
VONC

4
@BehrangSaeedzadeh: अपने आप में एक विद्रोह एक इतिहास को रैखिक नहीं बनायेगा। यह है कि आप अपनी featureशाखा के परिवर्तनों को वापस कैसे एकीकृत करते हैं master, यह कहा जाता है कि इतिहास रैखिक है या नहीं। एक साधारण तेज़-फ़ॉवर्ड मर्ज इसे रैखिक बना देगा। यह समझ में आता है कि यदि आपने उस featureशाखा के इतिहास को फास्ट-फॉरवर्ड मर्ज से पहले ही साफ कर दिया है , तो केवल महत्वपूर्ण कमिट छोड़कर, जैसा कि stackoverflow.com/questions/7425541/… में बताया गया है ।
VonC

42

मुझे VonC के बहुत व्यापक उत्तर पर थोड़ा विस्तार करने दें :


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

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


दूसरा, जब निम्न सर्वोत्तम प्रथाओं का उपयोग करने का फीचर शाखाओं , अर्थात् उस सुविधा शाखाओं स्थिर संस्करण (आमतौर पर अंतिम रिलीज से), से सभी शुरू करने के लिए सक्षम होने के लिए चाहिए चेरी लेने और है, जो चुन कर मर्ज करने के लिए कौन-सी विशेषता शाखाओं शामिल करने के लिए सुविधाओं का चयन आप आम तौर पर तेजी से आगे की स्थिति में नहीं होते हैं ... जो इस मुद्दे को मूक बना देता है। एक बहुत पहली शाखा को मर्ज करते समय आपको एक सही मर्ज बनाने और तेजी से आगे न बढ़ने की चिंता करने की आवश्यकता है (यह मानते हुए कि आप सीधे 'मास्टर' पर एकल-प्रतिबद्ध परिवर्तन नहीं करते हैं); अन्य सभी बाद के विलय गैर-फास्ट-फॉरवर्ड स्थिति में निश्चित रूप से हैं।

HTH


स्थिर रिलीज़ से सुविधा शाखाओं के बारे में: क्या होगा यदि मैं अगली रिलीज़ के लिए एक फ़ीचर विकसित कर रहा हूँ, एक अन्य फ़ीचर के बदलाव पर निर्भर करता है जिसे मैंने पहले ही विकसित कर लिया है और मास्टर में विलय हो गया है? निश्चित रूप से इसका मतलब है कि मुझे मास्टर से यह दूसरी सुविधा शाखा बनानी होगी?
dOxxx

1
@dOxxx: हां, इसके कुछ अपवाद हैं, जैसे कि जहां एक शाखा दूसरे पर निर्माण करती है (या तो सीधे, या मास्टर में पिछले विलय के बाद)।
जैकब नारबस्की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.