संघर्ष के बिना आसन्न रेखाओं का विलय क्यों नहीं होता?


25

मैंने हाल ही में सीखा है कि जब दो शाखाओं को git में मर्ज किया जाता है, अगर दो आसन्न लाइनों पर परिवर्तन होते हैं git इसे एक संघर्ष घोषित करता है। उदाहरण के लिए, यदि फ़ाइल test.txtमें यह सामग्री है:

Line 1: A
Line 2: B
Line 3: C
Line 4: D

और शाखा में masterहम इसे बदलते हैं

Line 1: A
Line 2: B1
Line 3: C
Line 4: D

शाखा में रहते हुए testingहम इसे बदल देते हैं

Line 1: A
Line 2: B
Line 3: C1
Line 4: D

और फिर testingमें विलय करने का प्रयास master, गिट एक विलय संघर्ष की घोषणा करता है। मेरी भोली उम्मीद यह थी कि विलय संघर्ष के बिना होगा और इससे उपज होगी:

Line 1: A
Line 2: B1
Line 3: C1
Line 4: D

मुझे यकीन है कि एक अच्छा कारण है कि git इस तरह विलय नहीं करता है। क्या कोई इसका कारण बता सकता है?


अरे मैंने पिछले हफ्ते भी यही देखा था। शायद हम एक ही ट्यूटोरियल कर रहे थे।
22

5
git की विलय की योग्यता वास्तव में काफी खराब है, IMO
जेम्स

@ जेम्स आपने धैर्य एल्गोरिथ्म का उपयोग करने की कोशिश की है? मुझे लगता है कि मुझे इसके साथ बेहतर परिणाम मिलते हैं, विशेष रूप से जब हॉक विभाजित होते हैं (जैसे दो के बजाय एक फ़ंक्शन बॉडी को हथियाने) के साथ काम करते हैं। यदि आपको git पसंद नहीं है, तो आप अपना स्वयं का उपयोग भी कर सकते हैं ( एक उदाहरण के लिए blog.wuwon.id.au/2010/09/… देखें )।
18

1
मूल कारण यह है कि गिट एक विशेष उपकरण से बाहर फैक्टरिंग के बजाय खुद को मर्ज करने की कोशिश करता है। पूरी तरह से यूनिक्स दर्शन नहीं है। स्रोत फ़ाइलों के लिए, आप वास्तव में भिन्नता निर्धारित करने के लिए भाषा व्याकरण का उपयोग कर सकते हैं।
MSalters

एकमात्र सामान्य संदर्भ A और D है, इसलिए A / C1 / B1 / D सही मर्ज क्यों नहीं है?
इज़्काता

जवाबों:


13

यह मानते हुए कि यह कोड का स्निपेट है

x=0
x+=1 if foo
x+=1 if bar
return x

इसे एक शाखा में बदल दिया गया है

x=0
x+=1 if foo && xyzzy
x+=1 if bar
return x

और इस में एक और शाखा में

x=0
x+=1 if foo
x+=1 if bar && xyzzy
return x

तब मैं यह नहीं चाहूंगा कि इसे इस में विलय किया जाए

x=0
x+=1 if foo && xyzzy
x+=1 if bar && xyzzy
return x

मुझे चिंता किए बिना।

ऐसी समस्याओं के कारण से बचने के लिए, गिट आमतौर पर पास की रेखाओं को छूने वाले परिवर्तनों को स्वचालित रूप से मर्ज करने से इनकार करते हैं। यह आपको यह सत्यापित करने का मौका देता है कि प्रोग्राम लॉजिक को तोड़ा जाएगा या नहीं।

यह उदाहरण तुच्छ है, लेकिन जब विशाल शाखाओं को मिलाते हैं तो समान "तार्किक" संघर्षों का जोखिम बहुत बड़ा होता है। कभी-कभी मुझे इस संदर्भ से भी बड़ा लगता है कि यह वर्तमान में भी बड़ा है।


5
हालांकि, इसका इससे कोई लेना-देना नहीं है, बस उन दोनों के बीच एक अपरिवर्तनीय रेखा जोड़ते हैं और अचानक एक समस्या के बिना उन्हें मिला देते हैं।
डार्कहॉग

हाँ, मुझे यह उत्तर नहीं मिला। आप सभी स्वचालित मर्जों से बचने के लिए एक ही तर्क का उपयोग कर सकते हैं।
मेहरदाद

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

11

क्या यह केवल-व्यवहार है?

एक सहकर्मी के साथ चर्चा के बाद, मैंने बस कोशिश की, और एसवीएन इसे समस्या के बिना संभालता है: आपको 2 पंक्तियों को संशोधित किया जाता है।

कई वीसीएस की मर्ज क्षमताओं का परीक्षण यहां बाजार, डार्क्स, गिट और मर्क्यूरियल के लिए किया जाता है : https://github.com/mndrix/merge-this

ऐसा लगता है कि केवल डारक्स "आसन्न लाइनों" मामले को सफलतापूर्वक मर्ज करते हैं।

फ़ाइलों में आसन्न परिवर्तन लागू करना कोई कठिन समस्या नहीं है। मुझे वास्तव में लगता है कि इस व्यवहार को उद्देश्य से चुना गया है।

कोई यह क्यों तय करेगा कि आसन्न रेखाओं को संशोधित करना एक संघर्ष पैदा करता है?

मुझे लगता है कि यह आपको इसे देखने के लिए मजबूर करना है

int max = MAX_ITEMS;
for(unsigned int i = 0; i < max; i++)
    do_stuff(i);

मोडिफ नंबर 1, मास्टर पर:

int max = MAX_ITEMS/2; // Do stuff only on the first half
for(unsigned int i = 0; i < max; i++)
    do_stuff(i);

मोडिफ नंबर 2, एक शाखा से विलय:

int max = MAX_ITEMS;
for(unsigned int i = 0; i < max/2; i++) // max/2: only on 1st half
    do_stuff(i);

मर्ज करने के बाद, आप ऐसा नहीं चाहते:

int max = MAX_ITEMS/2; // Do stuff only on the first half
for(unsigned int i = 0; i < max/2; i++) // max/2: only on 1st half
    do_stuff(i);

इस व्यवहार को एक सुविधा के रूप में देखना

आप git मर्जिंग व्यवहार को लाभ में बदल सकते हैं। जब आपको 2 पंक्तियों को लगातार रखने की आवश्यकता होती है, लेकिन आप इसका पता नहीं लगा सकते हैं (संकलन के समय, अपने परीक्षणों या अन्य समय पर), तो आप उनसे जुड़ने का प्रयास कर सकते हैं।

इसे फिर से लिखें ...:

for(unsigned int i = 0; i < max; i++)
    r = do_stuff(i);
    // Need to do something else
    do_something_else(r);

...इसके लिए:

for(unsigned int i = 0; i < max; i++)
    r = do_stuff(i);
    do_something_else(r); // Need to do something else

इसलिए जब आप मोडिफ 1 को मर्ज करते हैं ...:

for(unsigned int i = 0; i < max; i++)
    r = do_stuff(i)/2; // we need only the half
    do_something_else(r); // Need to do something else

... मोडिफ़ 2 के साथ ...:

for(unsigned int i = 0; i < max; i++)
    r = do_stuff(i);
    if(r < 0) // do_stuff can return an error
        handle_error(r);
    do_something_else(r/2); // Need to do something else

..., गिट संघर्ष पैदा करेगा, और आप इसे देखने के लिए मजबूर करेंगे।


2
मैं बस आगे बढ़ने जा रहा हूं और कहता हूं कि मुझे लगता है कि आपका उत्तर पूरी तरह से उचित है, लेकिन जटिल, कार्यान्वयन के आधार पर आपके कोड के बीच परिभाषित किया गया इंटरप्ले और पवित्रता की जाँच के लिए आपके स्रोत नियंत्रण thedailywtf.com के लिए एक तेज़ ट्रैक है। किसी भाषा पार्सर के बिना ब्लाइंडली मर्जिंग कोड वैसे भी हमेशा सबसे अच्छा प्रयास होता है, और मेरे पास कुछ उदाहरण हैं जहां git ने सहायक रूप से कुछ ऐसा किया है जो इसे नहीं होना चाहिए और कोड का उत्पादन किया जो कि संकलन भी नहीं करेगा।
पहना

5

मैं ज्यादातर अनुमान लगा रहा हूं, लेकिन मुझे लगता है कि लाइन 3 के बदलाव के लिए इसे संदर्भ के रूप में इस्तेमाल किया जा रहा है।

Git यह नहीं कह सकता है कि "C के साथ रेखा C1 के साथ एक रेखा बन गई" क्योंकि "C" के साथ एक और रेखा हो सकती है, इसलिए यह कहता है कि "C के साथ की रेखा, फ़ाइल के शुरू होने के बाद सही है, रेखा के साथ A, और B के साथ की रेखा अब C1 है "

यदि "बी के साथ लाइन" अब नहीं है, तो कुछ संदर्भ खो गए हैं, और गिट केवल मोटे तौर पर बता सकते हैं कि नई रेखा को कहां जाना है।


5
यह भी बहुत संभावना है कि सी बी पर निर्भर करता है, इसलिए एक भोला मर्ज परेशानी भरा हो सकता है, भले ही गिट "इसे कैसे जानता है"
Lucina

मेरा विश्वास करो Git केवल "सोचता है कि यह जानता है"। Git गलत अवधारणाओं का एक कब्रिस्तान है, जिसे सीधा करने की कोशिश की जा रही है!
user3833732

2

यहाँ अन्य उत्तर सभी बिंदु पर हैं, लेकिन मेरे लिए यह हमेशा एक अनावश्यक सीमा की तरह लग रहा था।

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

लेकिन मैं फिर भी चेतावनी देने के बाद इसे स्वचालित रूप से करने का विकल्प चाहता था। इसलिए मैंने एक कस्टम गिट मर्ज ड्राइवर लिखा, जो समीपवर्ती (या व्यक्तिगत) लाइनों पर परस्पर विरोधाभासी विलय कर सकता है:

यहाँ छवि विवरण दर्ज करें

यह मुझे एक बड़ी मात्रा में बचाता है, क्योंकि मैं एक परियोजना का प्रबंधन करता हूं जहां लोग अक्सर एक ही फाइल पर काम कर रहे हैं और बहुत सारे कोड को फिर से सक्रिय कर रहे हैं।

स्क्रिप्ट GPLHub पर GPLv3 + लाइसेंस के तहत उपलब्ध है। शायद आपको यह उपयोगी लगे:

https://github.com/paulaltin/git-subline-merge


4
किसी को यह समझाने का मन होगा कि इसे क्यों ठुकरा दिया गया? मैं यहां काफी नया हूं, इसलिए अगर मैंने कुछ गलत किया है तो मैं जानना चाहता हूं कि ऐसा क्या था जिससे मैं भविष्य में इससे बच सकूं। मुझे लगता है कि मेरी पोस्ट वास्तव में पूछे गए सवाल का जवाब नहीं देती है, लेकिन यह अभी भी प्रासंगिक है और मुझे लगता है कि यहां आने वाले ज्यादातर लोग जानना चाहते हैं कि जीआईटी ऐसा क्यों नहीं करता है, लेकिन इसके बारे में वे क्या कर सकते हैं (जैसा मैंने किया था जब मैंने किया था) पहली बार एक Google खोज से इस सवाल पर पहुंचे)।
डेल्टक्रुक्स

मैंने अभी तक इसकी कोशिश नहीं की है, लेकिन मैं इसे स्वचालित करने के लिए एक रास्ता तलाश रहा हूं, और यहां इसे पाकर खुशी हुई। धन्यवाद :) तुम कमाल हो।
मेहरदाद

1
कोई बात नहीं! मुझे आशा है कि आप इसे उपयोगी पाएंगे, और कृपया गितुब पर प्रतिक्रिया छोड़ने के लिए स्वतंत्र महसूस करें यदि आप मुद्दों में भाग लेते हैं या सुधार के लिए कोई सुझाव हैं। धन्यवाद!
deltacrux
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.