"डिफ्स" परिवर्तन की लिंग्वा फ़्रैंका हैं। वे संक्षिप्त कथाएँ हैं जो आपको बताती हैं क्या किसी चीज़ के दो संस्करणों के बीच स्थानांतरित हुआ है - स्रोत कोड, गद्य, एक डेटासेट - बिना आपको सब कुछ फिर से पढ़ने के लिए मजबूर किए। उन कुछ प्रतीकों (+, -, @@) के पीछे एल्गोरिदम, हेयुरिस्टिक्स और प्रारूपों का एक गहरा ढेर रहता है जो શ્રેષ્ઠતા, गति और मानवीय समझ को संतुलित करता है। यह लेख डिफ्स का एक व्यावहारिक, एल्गोरिदम-से-वर्कफ़्लो दौरा है: वे कैसे गणना किए जाते हैं, वे कैसे स्वरूप ित होते हैं, कैसे मर्ज उपकरण उनका उपयोग करते हैं, और बेहतर समीक्षाओं के लिए उन्हें कैसे ट्यून करें। रास्ते में, हम प्राथमिक स्रोतों और आधिकारिक दस्तावेज़ों में दावों को आधार देंगे - क्योंकि छोटे विवरण (जैसे कि व्हाइटस्पेस गिनती है या नहीं) वास्तव में मायने रखते हैं।
औपचारिक रूप से, एक डिफ एक सबसे छोटे संपादन स्क्रिप्ट (SES) का वर्णन करता है जो एक "पुराने" अनुक्रम को सम्मिलन और विलोपन का उपयोग करके "नए" में बदलने के लिए (और कभी-कभी प्रतिस्थापन, जिसे हटाएं+सम्मिलित करें के रूप में मॉडल किया जा सकता है)। व्यवहार में, अधिकांश प्रोग्रामर-फेसिंग डिफ्सलाइन-ओरिएंटेड होते हैं और फिर पठनीयता के लिए वैकल्पिक रूप से शब्दों या वर्णों में परिष्कृत होते हैं। कैनोनिकल आउटपुट संदर्भ और एकीकृत प्रारूप हैं; बाद वाला - जो आप आमतौर पर कोड समीक्षा में देखते हैं - एक संक्षिप्त हेडर और "हंक्स" के साथ आउटपुट को संपीड़ित करता है, प्रत्येक परिवर्तनों के आसपास के संदर्भ का एक पड़ोस दिखाता है। एकीकृत प्रारूप-u/--unified के माध्यम से चुना जाता है और यह पैचिंग के लिए वास्तविक मानक है; patch आम तौर पर संदर्भ पंक्तियों से लाभान्वित होता है परिवर्तनों को मजबूती से लागू करने के लिए।
जीएनयू diff मैनुअल उन स्विचों को सूचीबद्ध करता है जिन्हें आप तब चुनते हैं जब आप कम शोर और अधिक सिग्नल चाहते हैं - रिक्त स्थान को अनदेखा करना, संरेखण के लिए टैब का विस्तार करना, या एक "न्यूनतम" संपादन स्क्रिप्ट के लिए पूछना, भले ही यह धीमा हो (विकल्प संदर्भ)। ये विकल्प यह नहीं बदलते हैं कि दो फ़ाइलों के भिन्न होने का क्या मतलब है; वे बदलते हैं कि एल्गोरिथ्म कितनी आक्रामक तरीके से छोटे स्क्रिप्ट की खोज करता है और परिणाम मनुष्यों को कैसे प्रस्तुत किया जाता है।
अधिकांश टेक्स्ट डिफ्स सबसे लंबी आम सबसीक्वेंस (LCS) अमूर्तता पर बने हैं। क्लासिक डायनेमिक प्रोग्रामिंग LCS को O(mn) समय और स्थान में हल करती है, लेकिन यह बड़ी फ़ाइलों के लिए बहुत धीमी और मेमोरी-भूखी है। हिर्शबर्ग का एल्गोरिथ्म ने दिखाया कि रैखिक स्थान (अभी भी O(mn) समय) में डिवाइड-एंड-कॉनकर का उपयोग करके इष्टतम संरेखण की गणना कैसे करें, एक मूलभूत स्थान-बचत तकनीक जिसने व्यावहारिक डिफ कार्यान्वयन को प्रभावित किया।
गति और गुणवत्ता के लिए, सफलता यूजीन डब्ल्यू मायर्स का 1986 का एल्गोरिथ्मथा, जो O(ND) समय (N ≈ कुल लाइनें, D ≈ संपादन दूरी) और लगभग-रैखिक स्थान में एक SES पाता है। मायर्स एक "संपादन ग्राफ" में संपादन को मॉडल करता है औरसबसे दूर तक पहुंचने वाली सीमाओं के साथ आगे बढ़ता है, जिससे परिणाम मिलते हैं जो लाइन-डिफ सेटिंग में तेज और न्यूनतम के करीब दोनों हैं। यही कारण है कि "मायर्स" कई उपकरणों में डिफ़ॉल्ट बना हुआ है।
वहाँ भी हंट-स्ज़िमंस्की परिवार है, जो कुछ स्थितियों के मेल खाने पर LCS को तेज करता है (मैचों को पूर्व-अनुक्रमित करके और बढ़ते सबसीक्वेंस का पीछा करके), और ऐतिहासिक रूप से शुरुआती diff वेरिएंट से जुड़ा हुआ है। ये एल्गोरिदम ट्रेड-ऑफ को रोशन करते हैं: विरल मैचों के साथ इनपुट में, वे उप-द्विघ ात रूप से चल सकते हैं। सिद्धांत और कार्यान्वयन को जोड़ने वाले एक व्यवसायी के अवलोकन के लिए, देखें नील फ्रेजर के नोट्स।
मायर्स न्यूनतम संपादन स्क्रिप्ट का लक्ष्य रखता है, लेकिन "न्यूनतम" ≠ "सबसे पठनीय"। बड़े ब्लॉक पुन: व्यवस्थित या डुप्लिकेट किए गए एक शुद्ध SES एल्गोरिथ्म को अजीब संरेखण में फंसा सकते हैं। दर्ज करें धैर्य डिफ, ब्रैम कोहेन को श्रेय दिया जाता है: यह संरेखण को स्थिर करने के लिए अद्वितीय, कम-आवृत्ति वाली पंक्तियों पर लंगर डालता है, अक्सर ऐसे डिफ्स का उत्पादन करता है जिन्हें मनुष्य साफ-सुथरा पाते हैं - विशेष रूप से स्थानांतरित कार्यों या पुनर्गठित ब्लॉकों वाले कोड में। कई उपकरण इसे "धैर्य" विकल्प के माध्यम से उजागर करते हैं (उदाहरण के लिए,diff.algorithm)।
हिस्टोग्राम डिफ कम-घटना वाले तत्वों को बेहतर ढंग से संभालने के लिए एक आवृत्ति हिस्टोग्राम के साथ धैर्य का विस्तार करता है जबकि तेज रहता है ( JGitमें लोकप्रिय)। यदि आपने कभी पाया है कि --histogram शोर वाली फ़ाइलों के लिए स्पष्ट हंक्स का उत्पादन करता है, तो यह डिज़ाइन द्वारा है। आधुनिक गिट पर, आप एल्गोरिथ्म को विश्व स्तर पर या प्रति-आह्वान चुन सकते हैं:git config diff.algorithm myers|patience|histogram या git diff --patience।
लाइन डिफ्स संक्षिप्त होते हैं लेकिन छोटी-छोटी संपादनों को अस्पष्ट कर सकते हैं। शब्द-स्तरीय डिफ्स (--word-diff) पूरी-लाइन सम्मिलन/विलोपन के साथ समीक्षा को बाढ़ दिए बिना इंट्रा-लाइन परिवर्तनों को रंग देते हैं - गद्य, लंबी स्ट्रिंग्स या वन-लाइनर्स के लिए बढ़िया।
पुन: स्वरूपण के बाद व्हाइटस्पेस डिफ्स को दलदल कर सकता है। गिट और जीएनयू diff दोनों आपको स्थान परिवर्तनों को अनदेखा करने की अनुमति देते हैं विभिन्न डिग्री में और जीएनयू डिफ के व्हाइटस्पेस विकल्प (-b, -w, -B) मदद करते हैं जब एक स्वरूपक चलता है; आप संरेखण शोर के बजाय तार्किक संपादन देखेंगे।
जब कोड थोक में चलता है, तो गिट स्थानांतरित ब्लॉकों को हाइलाइट कर सकता है --color-moved के साथ, "स्थानांतरित" को "संशोधित" से दृष्टिगत रूप से अलग करता है, जो समीक्षकों को यह ऑडिट करने में मदद करता है कि एक चाल ने अनपेक्षित संपादनों को नहीं छिपाया है। इसे diff.colorMovedके माध्यम से स्थायी करें।
diff3एक दो-तरफा डिफ ठीक दो संस्करणों की तुलना करता है; यह नहीं बता सकता कि क्या दोनों पक्षों ने एक ही आधार रेखा को संपादित किया है, इसलिए यह अक्सर अति-संघर्ष करता है। तीन-तरफा मर्जिंग (आधुनिक VCS द्वारा उपयोग किया जाता है) प्रत्येक पक्ष के लिए एक आम पूर्वज से डिफ्स की गणना करता है और फिर दो परिवर्तन सेटों का मिलान करता है। यह नाटकीय रूप से नकली संघर्षों को कम करता है और बेहतर संदर्भ प्रदान करता है। यहाँ क्लासिक एल्गोरिथम कोर diff3है, जो "O" (आधार) से "A" और "B" में परिवर्तनों को मर्ज करता है और आवश्यकतानुसार संघर्षों को चिह्नित करता है।
अकादमिक और औद्योगिक कार्य मर्ज शुद्धता को औपचारिक बनाने और सुधारने के लिए जारी है; उदाहरण के लिए, सत्यापित तीन-तरफा मर्ज संघर्ष-स्वतंत्रता की शब्दार्थ धारणाओं का प्रस्ताव करते हैं। दिन-प्रतिदिन गिट में, आधुनिक ort मर्ज रणनीति कम आश्चर्य के साथ मर्ज का उत्पादन करने के लिए डिफिंग और नाम बदलने का पता लगाने पर बनाता है। उपयोगकर्ताओं के लिए, मुख्य सुझाव हैं: merge.conflictStyle=diff3के साथ संघर्षों में आधार रेखाएँ दिखाएं, और डिफ्स को छोटा रखने के लिए अक्सर एकीकृत करें।
पारंपरिक डिफ्स नाम बदलने को "देख" नहीं सकते क्योंकि सामग्री पता लगाना फ़ाइलों को ब्लॉब्स के रूप में मानता है; वे केवल एक विलोपन और एक जोड़ देखते हैं। नाम बदलने का पता लगाने की हेयुरिस्टिक्स जोड़े गए/हटाए गए जोड़े में समानता की तुलना करके उस अंतर को पाटती है। गिट में, इसे-M/--find-renames[=<n>] (डिफ़ॉल्ट ~50% समानता है) के माध्यम से सक्षम या ट्यून करें। शोर वाले चालों के लिए इसे कम करें। आप उम्मीदवार तुलनाओं को सीमित कर सकते हैं diff.renameLimit के साथ (और merge.renameLimit मर्ज के दौरान)। नाम बदलने के पार इतिहास का पालन करने के लिए, git log --follow -- <path>का उपयोग करें। हालिया गिट भी निर्देशिका-नाम बदलने का पता लगा ना करता है ताकि मर्ज के दौरान फ़ोल्डर चालों का प्रचार किया जा सके।
केवल टेक्स्ट ही नहीं बदलता है। बायनेरिज़ के लिए, आप आमतौर पर डेल्टा एन्कोडिंग चाहते हैं - एक स्रोत से एक लक्ष्य को फिर से बनाने के लिए कॉपी/ऐड निर्देश उत्सर्जित करें। rsync एल्गोरिथ्म ने एक नेटवर्क पर ब्लॉकों को संरेखित करने के लिए रोलिंग चेकसम का उपयोग करके कुशल दूरस्थ अंतर का बीड़ा उठाया, बैंडविड्थ को कम किया।
IETF ने एक सामान्य डेल्टा प्रारूप, VCDIFF (RFC 3284)को मानकीकृत किया, जिसमें ADD, COPY, और RUN का एक बाइटकोड वर्णित है, जिसमें xdelta3 जैसे कार्यान्वयन बाइनरी पैचिंग के लिए इसका उपयोग करते हैं। निष्पादन योग्य पर कॉम्पैक्ट पैच के लिए, bsdiff अक्सर प्रत्यय सरणियों और संपीड़न के माध्यम से बहुत छोटे डेल्टा का उत्पादन करता है; इसे तब चुनें जब पैच का आकार हावी हो और पीढ़ी ऑफ़लाइन हो सकती है।
जब आपको समवर्ती संपादनों या थोड़ी गलत संरेखित संदर्भों के सामने मजबूत पैचिंग की आवश्यकता होती है - संपादकों या सहयोगी प्रणालियों के बारे में सोचें - तो diff-match-patchपर विचार करें। यह मायर्स-शैली के अंतर को बिटैप फजी मैचिंग के साथ मिलाता है ताकि निकट-मैचों को ढूंढा जा सके और "सर्वश्रेष्ठ प्रयास" के रूप में पैच लागू किया जा सके, साथ ही प्री-डिफ स्पीडअप और पोस्ट-डिफ क्लीनअप जो एक अच्छा मानव आउटपुट के लिए थोड़ी सी न्यूनतमता का व्यापार करते हैं। निरंतर सिंक लूप में डिफ औ र फजी पैच को कैसे संयोजित करें, इसके लिए फ्रेजर का डिफरेंशियल सिंक्रोनाइज़ेशनदेखें।
CSV/TSV पर लाइन डिफ्स भंगुर होते हैं क्योंकि एक-सेल परिवर्तन एक पूरी-लाइन संपादन की तरह दिख सकता है। टेबल-अवेयर डिफ टूल (daff) डेटा को पंक्तियों/स्तंभों के रूप में मानते हैं, विशिष्ट कोशिकाओं को लक्षित करने वाले पैच उत्सर्जित करते हैं और विज़ुअलाइज़ेशन प्रस्तुत करते हैं जो परिवर्धन, विलोपन और संशोधनों को स्पष्ट करते हैं (देखें R विग्नेट)। त्वरित जांच के लिए, विशेष CSV डिफर सेल-बाय-सेल परिवर्तनों और प्रकार शिफ्ट को उजागर कर सकते हैं; वे एल्गोरिथम रूप से विदेशी नहीं हैं, लेकिन वे वास्तव में आपकी परवाह की संरचना की तुलना करके समीक्षा संकेत को बढ़ाते हैं।
--patience का प्रयास करें, या दोहराए जाने वाले पाठ पर तेज, पठनीय डिफ्स के लिए --histogram का प्रयास करें। git config diff.algorithm …के साथ एक डिफ़ॉल्ट सेट करें।-b, -w, --ignore-blank-lines) पर्याप्त परिवर्तनों पर ध्यान केंद्रित करने के लिए। गिट के बाहर, देखें जीएनयू डिफ के व्हाइटस्पेस नियंत्रण।--word-diff लंबी लाइनों और गद्य के लिए मदद करता है।--color-moved (या diff.colorMoved) "स्थानांतरित" को "संशोधित" से अलग करता है।-M जोड़ें या समानता सीमा को ट्वीक करें (-M90%, -M30%) नाम बदलने को पकड़ने के लिए; याद रखें कि डिफ़ॉल्ट लगभग 50% है। गहरे पेड़ों के लिए, diff.renameLimitसेट करें।git log --follow -- <path>।एक मर्ज दो डिफ्स (BASE→OURS, BASE→THEIRS) की गणना करता है और दोनों को BASE पर लागू करने का प्रयास करता है। ort जैसी रणनीतियाँ इसे बड़े पैमाने पर ऑर्केस्ट्रेट करती हैं, जिसमें नाम बदलने का पता लगाना (निर्देशिका-पैमाने पर चाल सहित) और संघर्षों को कम करने के लिए हेयुरिस्टिक्स शामिल हैं। जब संघर्ष होते हैं, --conflict=diff3 मार्कर्स को आधार संदर्भ के साथ समृद्ध करता है, जो समझने के लिए अमूल्य है इरादा। उन्नत मर्जिंग पर प्रो गिट अध ्याय समाधान पैटर्न के माध्यम से चलता है, और गिट के डॉक्स -X ours और -X theirsजैसे नॉब्स को सूचीबद्ध करते हैं। आवर्ती संघर्षों पर समय बचाने के लिए, rerere को अपने संकल्पों को रिकॉर्ड करने और फिर से चलाने के लिए सक्षम करें।
यदि आप एक नेटवर्क पर बड़ी संपत्ति सिंक कर रहे हैं, तो आप स्थानीय diff की तुलना में rsync दुनिया के करीब हैं। Rsync दूरस्थ रूप से मिलान करने वाले ब्लॉकों की खोज के लिए रोलिंग चेकसम की गणना करता है, फिर केवल वही स्थानांतरित करता है जो आवश्यक है। पैक किए गए डेल्टा के लिए, VCDIFF/xdelta आपको एक मानक बाइटकोड और परिपक्व उपकरण देता है; इसे तब चुनें जब आप एन्कोडर और डिकोडर दोनों को नियंत्रित करते हैं। और यदि पैच का आकार सर्वोपरि है (उदाहरण के लिए, ओवर-द-एयर फर्मवेयर), bsdiff बहुत छोटे पैच के लिए बिल्ड समय पर सीपीयू/मेमोरी का व्यापार करता है।
diff-match-patch जैसी लाइब्रेरी स्वीकार करती हैं कि, वास्तविक दुनिया में, जिस फ़ाइल को आप पैच कर रहे हैं, वह बह सकती है। एक ठोस डिफ (अक्सर मायर्स) को फजी मैचिंग (बिटैप) और विन्यास योग्य सफाई नियमों के साथ जोड़कर, वे एक पैच लागू करने के लिए सही जगह पा सकते हैं और डिफ को अधिक सुपाठ्य बना सकते हैं - सहयोगी संपादन और सिंकिंग के लिए महत्वपूर्ण।
-u/-U<n>) कॉम्पैक्ट और पैच-फ्रेंडली हैं; वे वही हैं जो कोड समीक्षा और CI उम्मीद करते हैं (संदर्भ)।git diff डॉक्स; जीएनयू व्हाइटस्पेस विकल्प)।diff3 -शैली के साथ तीन-तरफा कम भ्रामक है; ort प्लस नाम बदलने का पता लगाना मंथन को कम करता है; rerere समय बचाता है।क्योंकि मांसपेशियों की स्मृति मायने रखती है:
# अतिरिक्त संदर्भ के साथ एक मानक एकीकृत डिफ दिखाएं
git diff -U5
diff -u -U5 a b
# लंबी लाइनों या गद्य के लिए शब्द-स्तरीय स्पष्टता प्राप्त करें
git diff --word-diff
# पुन: स्वरूपण के बाद व्हाइटस्पेस शोर को अनदेखा करें
git diff -b -w --ignore-blank-lines
diff -b -w -B a b
# समीक्षा के दौरान स्थानांतरित कोड को हाइलाइट करें
git diff --color-moved
git config --global diff.colorMoved default
# नाम बदलने का पता लगाने के साथ रिफैक्टर को वश में करें और नाम बदलने के पार इतिहास का पालन करें
git diff -M
git log --follow -- <file>
# पठनीयता के लिए एल्गोरिथ्म को प्राथमिकता दें
git diff --patience
git diff --histogram
git config --global diff.algorithm patience
# संघर्ष मार्करों में आधार रेखाएँ देखें
git config --global merge.conflictStyle diff3महान डिफ्स न्यूनतमता साबित करने के बारे में कम और न्यूनतम संज्ञानात्मक लागत पर समीक्षक की समझ को अधिकतम करने के बारे में अधिक हैं। यही कारण है कि पारिस्थितिकी तंत्र ने कई एल्गोरिदम (मायर्स, धैर्य, हिस्टोग्राम), कई प्रस्तुतियाँ (एकीकृत, वर्ड-डिफ, कलर-मूव्ड), और डोमेन-जागरूक उपकरण (टेबल के लिए डैफ, बायनेरिज़ के लिए xdelta/bsdiff) विकसित किए। ट्रेड-ऑफ सीखें, नॉब्स को ट्यून करें, और आप लाल और हरी रेखाओं से संदर्भ को फिर से इकट्ठा करने में कम समय और इरादे के बारे में तर्क करने में अधिक समय व्यतीत करेंगे।
diff3 • व्हाइटस्पेस विकल्पडिफ़ एक उपकरण होता है या संस्करण नियंत्रण सिस्टम में प्रयोग होने वाली कार्यक्षमता जो दो संस्करणों या फ़ाइल की दो घटनाओं के बीच में अंतर को हाइलाइट करती है। इसे सामान्यतः फाइल में समय के साथ किए गए परिवर्तनों या अपडेट्स को ट्रैक करने के लिए उपयोग किया जाता है।
डिफ़ दो फ़ाइलों की तुलना रेखा-दर-रेखा करता है। यह पहली फ़ाइल की प्रत्येक रेखा के साथ द्वितीय फ़ाइल में अपने सम्मिलित हिस्से की स्कैन करता है, जैसे कि जोड़े जाने, हटाए जाने, या संशोधन के सभी महत्वपूर्ण अंतर दर्ज करता है।
पैच एक फ़ाइल होती है जिसमें दो फ़ाइलों के बीच के अंतर होते हैं, जो डिफ़ उपकरण द्वारा उत्पन्न किए जाते हैं। इसे फ़ाइल के एक संस्करण को "पैच" कमांड के साथ अपडेट करने के लिए इस्तेमाल किया जा सकता है ताकि इसे एक नए संस्करण में अपडेट किया जा सके।
संघीय डिफ़ एक प्रकार की डिफ़ फ़ाइल प्रारूप होती है जो परिवर्तनों को टेक्स्ट फ़ाइलों के लिए उपयुक्त फ़ाइल प्रारूप में प्रस्तुत करती है। यह मूल फ़ाइल से हटाए गए अंशों को ' - ' के साथ और मूल फ़ाइल में किए गए जोड़ों को ' + ' के साथ प्रदर्शित करता है।
डिफ़ संस्करण नियंत्रण सिस्टम में महत्वपूर्ण होते हैं क्योंकि वे टीमों को फ़ाइल में समय के साथ किए गए परिवर्तनों का हिसाब रखने में सक्षम बनाते हैं। यह ट् रैकिंग निरंतरता को बनाए रखने, काम को दोहराने से रोकने, त्रुटियों या असंगतियों को खोजने, और फ़ाइलों के एकाधिक संस्करणों को कुशलतापूर्वक प्रबंधित करने में मदद करती है।
सबसे लंबा सामान्य उपश्रेणी (LCS) एल्गोरिदम एक सामान्य विधि होती है जिसे डिफ़ टूल्स में इस्तेमाल किया जाता है ताकि मूल और संशोधित फ़ाइलों में बाईं-ओर-दाईं दिखाई देने वाले चरित्रों की सबसे लंबी श्रृंखला का पता लगाया जा सके। यह एल्गोरिदम दो फ़ाइलों के बीच मुख्य समानताओं और अंतरों की पहचान में मदद करता है।
अधिकांश मूल डिफ़ टूल्स केवल पाठ फ़ाइलों की तुलना कर सकते हैं। हालांकि, विशेषज्ञ डिफ़ टूल्स को बाइनरी फ़ाइलों की तुलना करने के लिए डिज़ाइन किया गया है, जो अंत रों को पठनीय प्रारूप में प्रदर्शित करते हैं।
सबसे लोकप्रिय डिफ़ टूल्स में GNU डिफ़, DiffMerge, KDiff3, WinMerge (Windows), और FileMerge (Mac) शामिल हैं। कई इंटीग्रेटेड डेवलपमेंट एन्वाइरनमेंट्स (IDEs) में भी डिफ़ उपयोगिताओं की सुविधा शामिल होती है।
Git में, आप `git diff` कमांड का उपयोग करके एक डिफ़ बना सकते हैं, जिसके बाद वे दो संस्करणों की फ़ाइलें होंगी जिनकी आपको तुलना करनी है। आउटपुट में दो फ़ाइलों के बीच में अंतर दिखाई देगा।
हां, कई डिफ़ टूल्स की क्षमता होती है कि वे व्यक्तिगत फ़ाइलों के अलावा निर्देशिकाओं की तुलना करें। जब अनेक फ़ाइलों वाले एक बड़े प्रोजेक्ट के संस्करणों की तुलना करते हैं, तो यह सुविधा विशेष रूप से उपयोगी हो सकती है।