🎧 Listen to this article: English
🌍 Read this in your language: हिंदी · தமிழ் · తెలుగు · ಕನ್ನಡ · മലയാളം · ଓଡ଼ିଆ · 日本語 · 中文
कोड में मर्ज कॉन्फ़्लिक्ट काफी परेशान करने वाले होते हैं। जब वे किसी इमेज फ़ाइल में होते हैं, तो ज़्यादातर लोग स्तब्ध रह जाते हैं — किसी चित्र के लिए कोई "diff view" नहीं होता है, और GitHub पर ब्राउज़र-में-ठीक-करें (fix-it-in-the-browser) वाला सामान्य बटन बस वहाँ नहीं होता है। यह पोस्ट ठीक उसी के एक वास्तविक मामले के बारे में बताती है: क्या काम नहीं किया, और क्या काम किया।
आज, 29 अगस्त 2026 तक, इसे समझना सार्थक है क्योंकि अधिक छोटी टीमें Git के माध्यम से कंटेंट-हैवी वेबसाइटें चलाती हैं, जिसमें गैर-तकनीकी लोग डेस्कटॉप ऐप के माध्यम से टेक्स्ट और इमेज में बदलाव करते हैं। वह मिश्रण — प्लेन-लैंग्वेज कंटेंट एडिटर, बाइनरी फ़ाइलें, और एक वास्तविक डिप्लॉय पाइपलाइन — ठीक वही जगह है जहाँ यह समस्या दिखाई देती है।
सेटअप: दो ब्रांच, एक साझा इमेज
प्रोजेक्ट एक साधारण दो-ब्रांच वर्कफ़्लो का उपयोग करता है। staging वह जगह है जहाँ दिन-प्रतिदिन का काम होता है — एक कंटेंट एडिटर वहाँ स्वतंत्र रूप से बदलाव पुश करता है, और यह स्वचालित रूप से एक प्रीव्यू साइट पर डिप्लॉय हो जाता है। main असली लाइव साइट है, जो केवल तभी अपडेट होती है जब एक रिव्यु किया गया पुल रिक्वेस्ट (Pull Request) staging से मर्ज किया जाता है।
टीम ने हाल ही में साइट की इमेज को WebP में बदला था, जो समान दृश्य गुणवत्ता पर PNG या JPG की तुलना में बहुत छोटा एक आधुनिक प्रारूप है। अब हर इमेज एक जोड़ी के रूप में मौजूद थी: मूल .png, और एक मेल खाता हुआ .webp, जिसे एक HTML के साथ जोड़ा गया है <picture> एलिमेंट ताकि WebP-सक्षम ब्राउज़र स्वचालित रूप से छोटी फ़ाइल प्राप्त कर सकें, और बाकी सब मूल पर वापस आ जाएं।
फिर लगभग एक ही समय में दो अलग-अलग ब्रांचों पर दो चीजें हुईं: किसी ने एक उत्पाद स्क्रीनशॉट में एक छोटा, सीधा संपादन (edit) किया mainपर, सामान्य रिव्यु फ्लो को बायपास करते हुए, जबकि कंटेंट एडिटर ने अलग से उसी स्क्रीनशॉट का वास्तव में नया वर्ज़न अपलोड किया stagingके माध्यम से। दोनों संपादनों (edits) ने एक ही फ़ाइल पथ (file path) को छुआ। किसी भी पक्ष को दूसरे के बारे में पता नहीं था।
GitHub की वेबसाइट इसे ठीक क्यों नहीं कर सकी
जब कंटेंट एडिटर ने अपडेट को staging लाने के लिए एक पुल रिक्वेस्ट (Pull Request) खोला mainमें, तो GitHub ने इसे तुरंत फ़्लैग किया: "This branch has conflicts that must be resolved." आम तौर पर, क्लिक करने से आपको एक वेब-आधारित एडिटर मिलता है जो एक टेक्स्ट फ़ाइल के दोनों संस्करणों को एक साथ दिखाता है, ताकि आप चुन सकें कि किन पंक्तियों को रखना है।
वह एडिटर इमेज के लिए मौजूद नहीं है। GitHub का ब्राउज़र-आधारित कॉन्फ़्लिक्ट रिज़ॉल्यूशन केवल लाइन-आधारित टेक्स्ट — कोड, मार्कडाउन, कॉन्फ़िगरेशन फ़ाइलें — को समझता है। तुलना करने के लिए PNG या WebP फ़ाइल में कोई "लाइनें" नहीं होती हैं। वेबसाइट के माध्यम से ऐसा कोई बटन, कोई दृश्य, कोई पथ नहीं था जो इसे हल कर सके, चाहे किसी ने कितनी भी सावधानी से क्लिक क्यों न किया हो। यह स्पष्ट रूप से कहना उचित है: कंटेंट एडिटर कुछ भी गलत नहीं कर रहा था। टूल के पास वास्तव में इस विशेष समस्या को हल करने का कोई तरीका नहीं था।
छिपी हुई दूसरी समस्या
इसे ठीक करने के लिए फ़ाइल के दोनों संस्करणों को स्थानीय रूप से पुल (pull) करने और उनकी सीधे तुलना करने की आवश्यकता थी — यहीं पर एक अधिक छिपी हुई समस्या सामने आई। नया स्क्रीनशॉट staging पर एक वास्तविक अपडेट था, जो पहले की तुलना में बड़ा और उच्च रिज़ॉल्यूशन वाला था। लेकिन इसकी जोड़ी गई WebP फ़ाइल को लंबे समय से नहीं छुआ गया था — आयाम (dimensions) भी मेल नहीं खाते थे। नया PNG 1024 गुणा 1024 पिक्सेल था; इसके बगल में बैठा WebP अभी भी 750 गुणा 750 था, जो पूरी तरह से इमेज के पहले के संस्करण से बचा हुआ था।
इसका मतलब था कि कॉन्फ़्लिक्ट में केवल "एक पक्ष चुनना" — किसी भी संस्करण को थोक (wholesale) में रखना — एक बेमेल जोड़ी को भेज (ship) देता। PNG नया स्क्रीनशॉट दिखाएगा, लेकिन कोई भी विज़िटर जिसका ब्राउज़र WebP (अधिकांश आधुनिक ब्राउज़र) पसंद करता है, चुपचाप एक पुरानी, गलत इमेज देखेगा। कॉन्फ़्लिक्ट संदेश गायब हो जाएगा; वास्तविक बग बिना किसी के ध्यान में आए शिप हो जाएगा।
चरण 1: दोनों संस्करणों की ठीक से तुलना करें
पहला कदम कुछ भी हल करना नहीं था — यह समझना था कि वास्तव में क्या और कहाँ बदल गया था, इसके लिए दोनों ब्रांचों पर फ़ाइल के आकार और आयामों (dimensions) की उनके सामान्य प्रारंभिक बिंदु से तुलना करना था।
git fetch origin
git diff --stat origin/main origin/staging -- path/to/image.png path/to/image.webp
इससे पता चला कि पिछली बार साझा किए जाने के बाद से दोनों ब्रांचों ने फ़ाइल को स्वतंत्र रूप से संशोधित किया था — एक वास्तविक तीन-तरफ़ा विचलन (three-way divergence), केवल "एक पक्ष नया है" ऐसा नहीं।
चरण 2: पहचानें कि वास्तव में कौन सा संस्करण सही था
दोनों PNG को एक साथ खोलने से पुष्टि हुई कि staging संस्करण ही वास्तविक, इच्छित अपडेट था, न कि कोई गलती या दूषित (corrupted) फ़ाइल।
चरण 3: सही स्रोत से WebP को पुन: उत्पन्न (Regenerate) करें
दो अलग-अलग बाइनरी फ़ाइलों को मर्ज करने का प्रयास करने के बजाय — जो संभव नहीं है — फिक्स यह था कि WebP को कुछ ऐसा माना जाए जो से प्राप्त (derived) हुआ हो PNG, न कि समाधान (reconcile) करने के लिए एक अलग फ़ाइल:
cwebp -q 82 image.png -o image.webp
इसने सही 1024 गुणा 1024 आयामों पर एक ताज़ा WebP तैयार किया, जो नए PNG से ठीक से मेल खाता है। -q 82 सिर्फ एक गुणवत्ता सेटिंग है — फ़ाइल आकार और तीक्ष्णता (sharpness) के बीच एक अच्छा संतुलन।
चरण 4: मर्ज पूरा करें और सत्यापित (verify) करें
git checkout staging
git merge origin/main
git checkout --ours path/to/image.png # keep the staging PNG
cp image-regenerated.webp path/to/image.webp # use the freshly regenerated WebP
git add path/to/image.png path/to/image.webp
git commit
git push origin staging
इसके बाद, पुल रिक्वेस्ट साफ़ और मर्ज करने योग्य दिखाई दिया, और लाइव साइट ने प्रत्येक विज़िटर को नया स्क्रीनशॉट सही ढंग से परोसा, चाहे वे WebP-सक्षम हों या नहीं।
विधियां जिन पर विचार किया गया, और जिन्हें अस्वीकार कर दिया गया
रास्ते में कुछ तेज़ दिखने वाले शॉर्टकट सामने आए, जिनमें से प्रत्येक के बारे में जानना उचित है, और यह जानना भी उचित है कि उनका उपयोग क्यों नहीं किया गया।
डेस्कटॉप Git क्लाइंट में एक संस्करण चुनना। ज़्यादातर Git डेस्कटॉप ऐप आपको "use my version" या "use theirs" चुनकर बाइनरी कॉन्फ़्लिक्ट को हल करने देते हैं — कोई तुलना नहीं, बस एक थोक चुनाव। एक गैर-तकनीकी टीम का सदस्य इसे स्वयं कर सकता है। दिक्कत यह है: इसने पुरानी, बेमेल WebP फ़ाइल को रखा होता, और ऊपर वर्णित वही मूक बग (silent bug) शिप कर दिया होता। तेज़, लेकिन गलत।
रणनीति फ़्लैग (strategy flag) के साथ मर्ज को बाध्य (Forcing) करना। कमांड लाइन से, git merge origin/main -X ours (या -X theirs) Git को यह बताने के लिए कि वह बिना रुके पूछे, प्रत्येक फ़ाइल के लिए पूरे एक पक्ष को चुनकर किसी भी कॉन्फ़्लिक्ट को स्वचालित रूप से हल करे:
git merge origin/main -X ours
इसमें डेस्कटॉप ऐप में कोई संस्करण चुनने जैसी ही खामी है — Git कॉन्फ़्लिक्ट वाली बाइनरी फ़ाइल को एक अविभाज्य ब्लॉक (indivisible block) के रूप में मानता है, इसलिए यह केवल बेमेल आधे हिस्से तक पहुंचकर उसे ठीक नहीं कर सकता है।
बेस ब्रांच से फ़ाइल को पहले हटाना (Deleting)। सिद्धांत: यदि लाइव ब्रांच में अब फ़ाइल नहीं है, तो कॉन्फ़्लिक्ट के लिए कुछ भी नहीं है, इसलिए मर्ज सफाई से होना चाहिए। इसे केवल मानने के बजाय सीधे एक अलग (isolated) ब्रांच में परीक्षण किया गया था:
git rm image.png image.webp
git commit -m "test: delete file"
git merge origin/staging
परिणाम एक क्लीन मर्ज नहीं था। Git को याद रहता है कि जब ब्रांच विभाजित (split) हुई थीं तब फ़ाइल मौजूद थी, इसलिए एक तरफ इसे हटाने (deleting) जबकि दूसरी तरफ यह बदलती है, फिर भी एक कॉन्फ़्लिक्ट पैदा होता है — एक "modify/delete" कॉन्फ़्लिक्ट, अपने स्वयं के चेतावनी संदेश के साथ। यह समस्या को छोड़ने (skipping) के बजाय उसे फिर से लेबल करता है।
कॉन्फ़्लिक्ट पर फ़ोर्स-पुशिंग (Force-pushing) करना। एक अधिक कठोर विकल्प फ़ोर्स पुश (force push) के माध्यम से अन्य ब्रांच के इतिहास के साथ लाइव ब्रांच को पूरी तरह से अधिलेखित (overwriting) करना है। यह वास्तव में कॉन्फ़्लिक्ट रिज़ॉल्यूशन नहीं है — यह किसी के वास्तविक कार्य के मूक नुकसान (silent loss) का जोखिम उठाते हुए, एक पक्ष के परिवर्तनों को पूरी तरह से त्याग रहा है। एक ऐसी ब्रांच पर जो लाइव साइट पर डिप्लॉय होती है, यह वास्तव में एक जोखिम भरा कदम है, न कि ऐसा शॉर्टकट जो अपनाने लायक हो।
निष्कर्ष
बाइनरी फ़ाइल कॉन्फ़्लिक्ट्स — इमेज, PDF, संकलित (compiled) फ़ाइलें, कुछ भी जो प्लेन टेक्स्ट नहीं है — को उस तरह से हल नहीं किया जा सकता जैसे कोड कॉन्फ़्लिक्ट्स को किया जा सकता है। तर्क करने के लिए कोई लाइन-बाय-लाइन diff नहीं है। एकमात्र वास्तविक विकल्प एक संस्करण को थोक (wholesale) में चुनना है, या, जब दो संस्करण वास्तव में एक इमेज और उसकी अनुकूलित (optimized) प्रति (copy) जैसी एक मेल खाने वाली जोड़ी (matched pair) हैं, तो सही स्रोत से व्युत्पन्न (derived) फ़ाइल को पुन: उत्पन्न (regenerate) करना है। यह समझना कि आप किस स्थिति में हैं, आधी लड़ाई जीतने के बराबर है।
गुण (Merits)
- व्युत्पन्न (derived) फ़ाइल (इस मामले में WebP) को पुन: उत्पन्न (Regenerating) करना यह अनुमान लगाने के बजाय कि किस पक्ष पर भरोसा किया जाए, स्थिरता की गारंटी देता है।
- किसी जोखिम भरे दिखने वाले शॉर्टकट पर भरोसा करने से पहले, एक अलग (isolated) ब्रांच में उसका परीक्षण करना, गलत धारणाओं को सस्ते में पकड़ लेता है।
- मूल फ़ाइल स्वरूप (format) को फ़ॉलबैक के रूप में पास रखना (एक
<picture>एलिमेंट के माध्यम से, इस मामले में) का अर्थ है कि अस्थायी रूप से टूटी हुई अनुकूलित प्रति (optimized copy) भी किसी विज़िटर के लिए पृष्ठ को कभी भी पूरी तरह से नहीं तोड़ती है।
दोष (Demerits)
- कोई भी तेज़ विकल्प (संस्करण-चुनें, बाध्य मर्ज रणनीति, हटाना और फिर से मर्ज करना) वास्तव में बेमेल-जोड़ी (mismatched-pair) की समस्या को हल नहीं करता है — वे केवल कॉन्फ़्लिक्ट संदेश को गायब कर देते हैं।
- इसे ठीक से ठीक करने के लिए सीधे सर्वर या कमांड-लाइन एक्सेस और एक इमेज-कन्वर्जन टूल की आवश्यकता थी, जो कि केवल ब्राउज़र या केवल डेस्कटॉप-ऐप वर्कफ़्लो जो कर सकता है, उसके बाहर है।
- अंतर्निहित कारण — सामान्य रिव्यु फ्लो को बायपास करते हुए, लाइव ब्रांच में सीधा संपादन — एक प्रक्रिया अंतर (process gap) है जिसे एक बार का तकनीकी सुधार फिर से होने से नहीं रोकता है।
सावधानी
यह लेख शैक्षिक है और सामान्य शब्दों में एक वास्तविक स्थिति का वर्णन करता है; विशिष्ट फ़ाइल नाम, पथ और पहचानकर्ताओं (identifiers) को सामान्यीकृत (generalized) किया गया है। यहां दिखाए गए कमांड वास्तविक फ़ाइलों और ब्रांच इतिहास को संशोधित या छोड़ सकते हैं — हमेशा पहले एक अलग ब्रांच या थ्रोअवे कॉपी में परीक्षण करें, सुनिश्चित करें कि आप समझते हैं कि आपकी विशिष्ट स्थिति में "ours" और "theirs" किस दिशा की ओर इशारा करते हैं, और पुष्टि करें कि बलपूर्वक कॉन्फ़्लिक्ट को हल करने वाली किसी भी चीज़ को चलाने से पहले आपके पास बैकअप या पुनर्प्राप्त करने का कोई तरीका है। किसी भी कमांड पर भरोसा करने से पहले उसे अपनी स्वयं की रिपॉजिटरी की वास्तविक स्थिति के विरुद्ध सत्यापित करें।
अक्सर पूछे जाने वाले प्रश्न
- GitHub की वेबसाइट इमेज फ़ाइलों में कॉन्फ़्लिक्ट को हल क्यों नहीं कर सकती? — इसका ब्राउज़र-आधारित कॉन्फ़्लिक्ट एडिटर केवल लाइन-आधारित टेक्स्ट को समझता है; उस इंटरफ़ेस के माध्यम से PNG या WebP जैसे बाइनरी डेटा की तुलना या मर्ज करने का कोई तरीका नहीं है।
- "modify/delete" कॉन्फ़्लिक्ट क्या है? — ऐसा तब होता है जब एक ब्रांच किसी फ़ाइल को हटा (delete) देती है और दूसरी ब्रांच उसे बदल देती है, जब से उन्होंने पिछली बार इतिहास साझा किया था; Git यह अनुमान लगाने के बजाय कि कौन सा बदलाव जीतना चाहिए, इसे फ़्लैग करता है।
- क्या एक ब्रांच से फ़ाइल हटाने से मर्ज कॉन्फ़्लिक्ट से बचा जा सकता है? — नहीं। यदि फ़ाइल मौजूद थी जब ब्रांच विचलित (diverged) हुई थीं, तो इसे एक तरफ हटाने और दूसरी तरफ इसे संशोधित करने पर भी एक कॉन्फ़्लिक्ट उत्पन्न होता है, बस एक अलग प्रकार का।
- क्या डेस्कटॉप Git क्लाइंट में "use my version" या "use theirs" इमेज कॉन्फ़्लिक्ट के लिए सुरक्षित है? — यह कॉन्फ़्लिक्ट को हल करता है, लेकिन केवल एक फ़ाइल को ज्यों का त्यों (as-is) रखकर; WebP कॉपी जैसा व्युत्पन्न (derived) समकक्ष (counterpart) अपने आप ठीक नहीं होगा।
- क्या
git merge -X oursवास्तव में करता है? — यह Git को बिना रुके पूछे, पूरे मर्ज के लिए वर्तमान ब्रांच के संस्करण को रखकर प्रत्येक कॉन्फ़्लिक्टिंग फ़ाइल को स्वचालित रूप से हल करने के लिए कहता है। - WebP फ़ाइल को केवल मर्ज करने के बजाय उसे पुन: उत्पन्न (regenerate) क्यों करें? — यह मूल इमेज का संपीड़ित व्युत्पन्न (compressed derivative) है; दो अलग-अलग संपीड़ित संस्करणों को "मर्ज" करने का कोई सार्थक तरीका नहीं है, इसलिए इसे सही स्रोत से फिर से बनाना ही एकमात्र सही फिक्स है।
- टीमें इस तरह के कॉन्फ़्लिक्ट से शुरुआत में ही कैसे बचती हैं? — एक सुसंगत (consistent) प्रवाह (flow) रखकर जहाँ सभी परिवर्तन लाइव ब्रांच तक पहुँचने से पहले एक वर्किंग ब्रांच से होकर गुज़रते हैं, बजाय इसके कि कई स्थानों से लाइव ब्रांच में सीधे संपादन की अनुमति दी जाए।
टैग (Tags)
#git #github #webp #imageoptimization #webdev #devops #versioncontrol #mergeconflict #cicd #webperformance
Linux Server Hardening Checklist
30 practical steps to take a fresh Linux box from default to defensible. Enter your email — you'll get the PDF instantly, plus new posts on Linux, security & AI.
Free. No spam — unsubscribe in one click.


Responses
Sign in to leave a response.