हमारे पास 400 से अधिक कमिट्स के साथ जीआईटी रिपॉजिटरी है, जिनमें से पहले एक दर्जन से अधिक ट्रायल-एंड-एरर थे। हम एक ही प्रतिबद्ध में कई नीचे स्क्वीज करके इन कमिट्स को साफ करना चाहते हैं। स्वाभाविक रूप से, गिट-रिबेस को जाने का रास्ता लगता है। मेरी समस्या यह है कि यह मर्ज संघर्षों के साथ समाप्त होता है, और इन संघर्षों को हल करना आसान नहीं है। मुझे समझ में नहीं आ रहा है कि किसी भी तरह का टकराव क्यों होना चाहिए, क्योंकि मैं सिर्फ हंगामा कर रहा हूं (हटाए या पीछे नहीं हट रहा)। बहुत संभावना है, यह दर्शाता है कि मैं पूरी तरह से समझ नहीं पा रहा हूं कि गिट-रिबेस अपने स्क्वैश को कैसे करता है।
यहां उन लिपियों का संशोधित संस्करण दिया गया है, जिनका मैं उपयोग कर रहा हूं:
repo_squash.sh (यह वास्तव में चलाई जाने वाली स्क्रिप्ट है):
rm -rf repo_squash
git clone repo repo_squash
cd repo_squash/
GIT_EDITOR=../repo_squash_helper.sh git rebase --strategy theirs -i bd6a09a484b8230d0810e6689cf08a24f26f287a
repo_squash_helper.sh (यह स्क्रिप्ट केवल repo_squash.sh द्वारा उपयोग की जाती है):
if grep -q "pick " $1
then
# cp $1 ../repo_squash_history.txt
# emacs -nw $1
sed -f ../repo_squash_list.txt < $1 > $1.tmp
mv $1.tmp $1
else
if grep -q "initial import" $1
then
cp ../repo_squash_new_message1.txt $1
elif grep -q "fixing bad import" $1
then
cp ../repo_squash_new_message2.txt $1
else
emacs -nw $1
fi
fi
repo_squash_list.txt: (यह फ़ाइल केवल repo_squash_helper.sh द्वारा उपयोग की जाती है)
# Initial import
s/pick \(251a190\)/squash \1/g
# Leaving "Needed subdir" for now
# Fixing bad import
s/pick \(46c41d1\)/squash \1/g
s/pick \(5d7agf2\)/squash \1/g
s/pick \(3da63ed\)/squash \1/g
मैं आपकी कल्पना में "नया संदेश" सामग्री छोड़ दूंगा। प्रारंभ में, मैंने "--strstryss" विकल्प के बिना ऐसा किया था (यानी, डिफ़ॉल्ट रणनीति का उपयोग करके, जिसे अगर मैं समझता हूं कि दस्तावेज़ सही रूप से पुनरावर्ती है, लेकिन मुझे यकीन नहीं है कि कौन सी पुनरावर्ती रणनीति का उपयोग किया जाता है), और यह भी नहीं था ' t काम। इसके अलावा, मुझे यह इंगित करना चाहिए कि, repo_squash_helper.sh में टिप्पणी किए गए कोड का उपयोग करके, मैंने मूल फ़ाइल को सहेज लिया है कि sed स्क्रिप्ट काम करती है और इसके खिलाफ sed स्क्रिप्ट चलती है यह सुनिश्चित करने के लिए कि यह वही कर रही थी जो मैं इसे करना चाहता था ( ये था)। फिर, मैं भी नहीं जानता कि क्यों हैं , विरोध हो तो यह इतना जो रणनीति प्रयोग किया जाता है कोई फर्क ही नहीं होता। किसी भी सलाह या अंतर्दृष्टि मददगार होगी, लेकिन ज्यादातर मैं सिर्फ इस स्क्वाश को काम करना चाहता हूं।
Jefromi के साथ चर्चा से अतिरिक्त जानकारी के साथ अद्यतन:
हमारे बड़े पैमाने पर "वास्तविक" रिपॉजिटरी पर काम करने से पहले, मैंने परीक्षण रिपॉजिटरी पर समान स्क्रिप्ट का उपयोग किया। यह एक बहुत ही सरल भंडार था और परीक्षण ने सफाई से काम किया।
यह विफल होने पर मुझे मिलने वाला संदेश है:
Finished one cherry-pick.
# Not currently on any branch.
nothing to commit (working directory clean)
Could not apply 66c45e2... Needed subdir
यह पहली स्क्वैश कमिटमेंट के बाद पहली पिक है। रनिंग git status
एक क्लीन वर्किंग डायरेक्टरी देता है। यदि मैं तब करता हूं, तो git rebase --continue
मुझे कुछ और आने के बाद एक समान संदेश मिलता है। यदि मैं इसे फिर से करता हूं, तो मुझे एक दर्जन के बाद एक और समान संदेश मिलता है। अगर मैं इसे अभी तक फिर से करता हूं, तो इस समय यह लगभग सौ कमिट्स के माध्यम से जाता है, और इस संदेश को देता है:
Automatic cherry-pick failed. After resolving the conflicts,
mark the corrected paths with 'git add <paths>', and
run 'git rebase --continue'
Could not apply f1de3bc... Incremental
अगर मैं दौड़ता git status
हूं, तो मुझे मिलता है:
# Not currently on any branch.
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: repo/file_A.cpp
# modified: repo/file_B.cpp
#
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: repo/file_X.cpp
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: repo/file_Z.imp
"दोनों संशोधित" बिट मुझे अजीब लगता है, क्योंकि यह सिर्फ एक पिक का परिणाम था। यह भी ध्यान देने योग्य है कि अगर मैं "संघर्ष" को देखता हूं, तो यह एक एकल पंक्ति में उबलता है, जिसमें एक संस्करण इसकी शुरुआत [टैब] वर्ण के साथ होता है, और दूसरा चार स्थानों के साथ होता है। यह लग रहा था कि यह एक समस्या हो सकती है कि मैंने अपनी कॉन्फ़िग फ़ाइल कैसे सेट की है, लेकिन इसमें कुछ भी नहीं है। (मैंने ध्यान दिया कि core.ignorecase सही पर सेट है, लेकिन जाहिर तौर पर git-clone ने स्वचालित रूप से ऐसा किया है। मुझे यह देखकर बिल्कुल आश्चर्य नहीं होगा कि मूल स्रोत विंडोज मशीन पर था।)
यदि मैं मैन्युअल रूप से file_X.cpp को ठीक करता हूं, तो यह एक और संघर्ष के बाद शीघ्र ही विफल हो जाता है, इस बार एक फ़ाइल (CMakeLists.txt) के बीच है कि एक संस्करण का मानना है कि मौजूद होना चाहिए और एक संस्करण को नहीं सोचना चाहिए। यदि मैं यह कहकर इस विरोध को ठीक कर दूं कि मुझे यह फ़ाइल चाहिए (जो मैं करता हूं), कुछ बाद में मुझे एक और संघर्ष (इसी फ़ाइल में) मिलता है जहां अब कुछ गैर-तुच्छ परिवर्तन हैं। यह अभी भी संघर्ष के माध्यम से लगभग 25% है।
मुझे यह भी इंगित करना चाहिए, क्योंकि यह बहुत महत्वपूर्ण हो सकता है, कि यह परियोजना एक svn रिपॉजिटरी में शुरू हुई थी। उस प्रारंभिक इतिहास को उस svn भंडार से आयात किया गया था।
अपडेट # 2:
एक लार्क पर (जेफ्रोमी की टिप्पणियों से प्रभावित), मैंने अपने repo_squash.sh को बदलने का फैसला किया:
rm -rf repo_squash
git clone repo repo_squash
cd repo_squash/
git rebase --strategy theirs -i bd6a09a484b8230d0810e6689cf08a24f26f287a
और फिर, मैंने अभी मूल प्रविष्टियों को स्वीकार किया है, जैसा कि है। यानी, "रिबेस" को एक चीज़ नहीं बदलनी चाहिए थी। यह पूर्व में वर्णित समान परिणामों के साथ समाप्त हुआ।
अपडेट # 3:
वैकल्पिक रूप से, यदि मैं रणनीति को छोड़ देता हूं और अंतिम कमांड को प्रतिस्थापित करता हूं:
git rebase -i bd6a09a484b8230d0810e6689cf08a24f26f287a
मुझे अब रिबास समस्याओं के लिए "कुछ भी नहीं करने के लिए" नहीं मिलता है, लेकिन मैं अभी भी अन्य संघर्षों के साथ बचा हुआ हूं।
खिलौना रिपॉजिटरी के साथ अद्यतन जो समस्या को फिर से बनाता है:
test_squash.sh (यह वह फ़ाइल है जिसे आप वास्तव में चलाते हैं):
#========================================================
# Initialize directories
#========================================================
rm -rf test_squash/ test_squash_clone/
mkdir -p test_squash
mkdir -p test_squash_clone
#========================================================
#========================================================
# Create repository with history
#========================================================
cd test_squash/
git init
echo "README">README
git add README
git commit -m"Initial commit: can't easily access for rebasing"
echo "Line 1">test_file.txt
git add test_file.txt
git commit -m"Created single line file"
echo "Line 2">>test_file.txt
git add test_file.txt
git commit -m"Meant for it to be two lines"
git checkout -b dev
echo Meaningful code>new_file.txt
git add new_file.txt
git commit -m"Meaningful commit"
git checkout master
echo Conflicting meaningful code>new_file.txt
git add new_file.txt
git commit -m"Conflicting meaningful commit"
# This will conflict
git merge dev
# Fixes conflict
echo Merged meaningful code>new_file.txt
git add new_file.txt
git commit -m"Merged dev with master"
cd ..
#========================================================
# Save off a clone of the repository prior to squashing
#========================================================
git clone test_squash test_squash_clone
#========================================================
#========================================================
# Do the squash
#========================================================
cd test_squash
GIT_EDITOR=../test_squash_helper.sh git rebase -i HEAD@{7}
#========================================================
#========================================================
# Show the results
#========================================================
git log
git gc
git reflog
#========================================================
test_squash_helper.sh (test_sqash.sh द्वारा प्रयुक्त):
# If the file has the phrase "pick " in it, assume it's the log file
if grep -q "pick " $1
then
sed -e "s/pick \(.*\) \(Meant for it to be two lines\)/squash \1 \2/g" < $1 > $1.tmp
mv $1.tmp $1
# Else, assume it's the commit message file
else
# Use our pre-canned message
echo "Created two line file" > $1
fi
पुनश्च: हाँ, मैं आप में से कुछ को जानता हूँ जब आप मुझे एक पतन-संपादक के रूप में emacs का उपयोग करते हुए देखते हैं।
पीपीएस: हम जानते हैं कि हमें रिबास के बाद मौजूदा रिपॉजिटरी के हमारे सभी क्लोन को उड़ाना होगा। ("प्रकाशित होने के बाद" आप किसी भंडार को पुन: प्रकाशित नहीं करेंगे ") की तर्ज पर।"
PPPS: क्या कोई मुझे बता सकता है कि इसमें कोई इजाफा कैसे किया जाए? मैं इस स्क्रीन पर कहीं भी विकल्प नहीं देख रहा हूं चाहे मैं संपादन मोड में हूं या दृश्य मोड में हूं।
rebase --interactive
- जो प्रयास करने के लिए गिट की कार्रवाई की सूची की तरह हैं। मैं उम्मीद कर रहा था कि आप इसे एक एकल स्क्वैश को कम करने में सक्षम हो सकते हैं जो संघर्ष पैदा कर रहा था, और आपकी सहायक लिपियों की सभी अतिरिक्त जटिलता से बचें। अन्य लापता जानकारी तब होती है जब संघर्ष होता है - जब गिट स्क्वैश बनाने के लिए पैच लागू करता है, या जब यह स्क्वैश पर आगे बढ़ने और अगले पैच को लागू करने की कोशिश करता है? (और क्या आपको यकीन है कि आपके GIT_EDITOR कीचड़ के साथ कुछ बुरा नहीं होता है? सरल परीक्षण के मामले में एक और वोट।)
rebase -p
वैसे भी उपयोग नहीं कर रहे हैं )