क्या गैर-संवादात्मक रूप से कई हिट करने का एक तरीका है?


115

मैं हिट की एक सीमा स्क्वैश करने की कोशिश कर रहा हूँ - सिर से सिर ~ 3। क्या ऐसा करने का कोई त्वरित तरीका है, या क्या मुझे रिबेस-इनएक्टिव का उपयोग करने की आवश्यकता है?


5
इसी तरह के सवाल: stackoverflow.com/questions/5189560/…
koppor

जवाबों:


146

सुनिश्चित करें कि आपका काम करने वाला पेड़ साफ है, फिर

git reset --soft HEAD~3
git commit -m 'new commit message'

@ विल्हेमटेल: शानदार! अब क्या मैं एक git उपनाम का निर्माण कर पाऊंगा, जैसे "mysquash 3 'कुछ संदेश'", इसे एक पंक्ति में नीचे करने के लिए?
फिलिप

5
यदि इसकी मात्र रेखाएँ हैं:git reset --soft HEAD~3 && git commit -m "my message"
KingCrunch

7
@Phillip: आप गिट उपनाम में एक शेल फ़ंक्शन एम्बेड कर सकते हैं। git config alias.mysquash '!f(){ git reset --soft HEAD~$1 && git commit ${2:+-m "$2"}; };f'git mysquash 3 'some message'काम करेगा, लेकिन मैंने इसे भी बदल दिया ताकि मैं git musquash 3पूरी तरह से झंडे को छोड़ दूं ताकि आपको git commitउस मामले में इंटरैक्टिव यूआई मिल जाए ।
लिली बॉलर

3
बस इसे स्पष्ट करने के लिए: यह स्क्वैश के समान नहीं है। एक स्क्वैश भी प्रतिबद्ध संदेशों को मर्ज करेगा। यदि आप एक नरम रीसेट करते हैं तो आप कमिट के सभी संदेश खो देंगे। आप स्क्वैश कोशिश करना चाहते हैं stackoverflow.com/a/27697274/974186
रेने लिंक

1
@sebnukem - जब हम शाखा को धकेलने का प्रयास करते हैं और बल पुश को अस्वीकार करने के लिए रिमोट को कॉन्फ़िगर किया जाता है।
अवमोहन

30

मुझे व्यक्तिगत रूप से विल्हेमटेल का समाधान पसंद है :

git reset --soft HEAD~3
git commit -m 'new commit message'

हालाँकि, मैंने कुछ त्रुटि जाँच के साथ एक उपनाम बनाया ताकि आप ऐसा कर सकें:

git squash 3 'my commit message'

मैं उपनामों की स्थापना करने की सलाह देता हूं जो वास्तव में स्क्रिप्ट चलाते हैं ताकि आपकी स्क्रिप्ट्स को (ए) कोड करना आसान हो और (बी) त्रुटि जांच के साथ अधिक जटिल काम करें। नीचे एक स्क्रिप्ट दी गई है जो स्क्वैश का काम करती है और फिर उसके नीचे आपके गिट एलियास को स्थापित करने की स्क्रिप्ट है।

स्क्वैश के लिए स्क्रिप्ट (स्क्वैश.श)

#!/bin/bash
#

#get number of commits to squash
squashCount=$1

#get the commit message
shift
commitMsg=$@

#regular expression to verify that squash number is an integer
regex='^[0-9]+$'

echo "---------------------------------"
echo "Will squash $squashCount commits"
echo "Commit message will be '$commitMsg'"

echo "...validating input"
if ! [[ $squashCount =~ $regex ]]
then
    echo "Squash count must be an integer."
elif [ -z "$commitMsg" ]
then
    echo "Invalid commit message.  Make sure string is not empty"
else
    echo "...input looks good"
    echo "...proceeding to squash"
    git reset --soft HEAD~$squashCount
    git commit -m "$commitMsg"
    echo "...done"
fi

echo
exit 0

फिर उस स्क्वाश स्क्रिप्ट को git उपनाम के लिए हुक करने के लिए, अपने git उपनाम को सेट करने के लिए एक और स्क्रिप्ट बनाएं, जैसे ( create_aliases.command या create_aliases.sh ):

#!/bin/sh
echo '-----------------------'
echo 'adding git aliases....'
echo '-----------------------'
echo
git config --global alias.squash "!bash -c 'bash <path to scripts directory>/squash.sh \$1 \$2' -"
#add your other git aliases setup here
#and here
#etc.
echo '------------------------------------'
echo 'here is your global gitconfig file:'
echo '------------------------------------'
more ~/.gitconfig
echo 
echo
echo '----------------'
echo 'end of script...'
echo '----------------'

4
आप इसे $PATHनाम में भी रख सकते हैं git-squash.shऔर यह स्वचालित रूप से अलियास हो जाएगा git squash। मैंने आपका उत्तर नहीं बदला है, बस उस स्थिति में create-aiases.shस्क्रिप्ट का उपयोग करने का एक कारण है जिसके बारे में मुझे जानकारी नहीं है।

मैं मूल रूप से create_aliases.command स्क्रिप्ट का उपयोग करता हूं ताकि हमारे पीएम और डिजाइनर भी आसानी से सेट हो सकें। बस स्क्रिप्ट पर एक डबल-क्लिक करें और वे सभी सेट हैं (विशेषकर जब से मेरे रिपो में सेटअप स्क्रिप्ट है और रिश्तेदार पथ ज्ञात है)। फिर उन्हें टर्मिनल को पुनरारंभ करने की भी आवश्यकता नहीं है।
n8tr

1
मैंने यह कोशिश की और यह मेरे प्रतिबद्ध संदेश को स्क्वैश काउंट के रूप में पढ़ता है और विफल हो जाता है क्योंकि यह पूर्णांक नहीं है।
मिन्टोस

1
समाधान के लिए संलग्न करना था - /squash.sh \ $ 1 \ $ 2 'के बाद
Minthos

1
मुझे समाधान का विचार पसंद है, लेकिन समाधान में उपरोक्त टिप्पणी को अभी तक ध्यान में नहीं लिया गया है। सिंगल और डबल कोट के बीच माइनस साइन होना चाहिए।
physicalattraction

10

विल्हेमटेल द्वारा उत्तर में जोड़ने के लिए मैं इसे HEAD~2फिर से नरम रीसेट करने के लिए सुविधाजनक बनाता हूं और फिर की प्रतिबद्धता में संशोधन कर रहा हूं HEAD~3:

git reset --soft HEAD~2
git commit --all --amend --no-edit    

यह सभी कमिट्स को HEAD~3कमिट में मर्ज कर देगा और इसके कमिट मैसेज का उपयोग करेगा। एक साफ काम करने वाले पेड़ से शुरू करना सुनिश्चित करें।


2
यह सही उत्तर है क्योंकि यह सिर पर आने वाले कमिट की एक श्रृंखला को स्क्वैश करता है, और यह 1 कमिट के संदेश का उपयोग करता है। यह गैर-संवादात्मक है।
लैंडन कुहन

9

मैंनें इस्तेमाल किया:

EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>

काफी ठीक काम किया। बस "पिक" से शुरू होने वाली लाइन के साथ कमिट लॉग करने की कोशिश न करें :)


अफसोस की बात है कि यह विंडोज पर मेरे लिए काम नहीं करता है। अभी भी इंटरैक्टिव संपादक मिलता है।
abergmeier

3

अंतिम आदेश के भीतर अंतिम 4 कमिट्स को स्क्वैश करने के लिए निम्न कमांड का उपयोग करें:

git squash 4

उपनाम के साथ:

squash = !"f() { NL=$1; GIT_EDITOR=\"sed -i '2,$NL s/pick/squash/;/# This is the 2nd commit message:/,$ {d}'\"; git rebase -i HEAD~$NL; }; f"
sq = !git squash $1
sqpsf = !git squash $1 && git psf 

से https://github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig


आपने यह निर्दिष्ट नहीं किया कि यहाँ OS / शेल का क्या उपयोग किया जा रहा है। यह समाधान संभवतः उन सभी अन्य डेस्कटॉप के लिए काम नहीं करेगा जिनका लोग उपयोग करते हैं।
रिक -777

हाँ, आपको इसके लिए linux / bash का उपयोग करना चाहिए | zsh
brauliobo

2

यहाँ एक लाइनर है जो अंतिम 2 को स्क्वैश करता है। इस उदाहरण में, दूसरी अंतिम प्रतिबद्धता का संदेश बरकरार रखा जाएगा। आप अपनी इच्छानुसार संदेश बदल सकते हैं।

git commit -am "$(git log -1 --skip=1 --pretty=%B | xargs && git reset --soft HEAD~2)"

यदि आप इस कमांड के लिए एक उपनाम बनाते हैं और इसके बजाय अन्य नाम का उपयोग करते हैं तो यह कमांड बहुत उपयोगी होगी।


1

सब कुछ स्क्वैश करने के लिए क्योंकि शाखा को मास्टर से कांटा गया था:

git reset --soft $(git merge-base --fork-point master) \
  && git commit --verbose --reedit-message=HEAD --reset-author

--reedit-message=HEADअंतिम प्रतिबद्ध के संदेश का उपयोग करेगा जो स्क्वैश का हिस्सा नहीं है । यह संभवत: वह नहीं है जो आप चाहते हैं। पहले शामिल किए जाने के संदेश को शामिल करने के लिए , या तो (1)HEAD आप जिस संदेश को चाहते हैं, उसके हैश के साथ बदलें , या (2) पहली बार शामिल होने के लिए कूदें और git commit --amend --reedit-message=HEAD। यह सामंजस्यपूर्ण उत्तर है।
मैलान

-1

आप के साथ बहुत करीब हो सकते हैं

जीआईटी रिबास - अटलांटा हेड ~ 4 हेड ~ मास्टर

यह मानता है कि आप एक रैखिक इतिहास के साथ मास्टर हैं। यह काफी स्क्वैश नहीं है क्योंकि यह इंटरमीडिएट कमिट्स को डिस्कस करता है। आपको प्रतिबद्ध संदेश को संशोधित करने के लिए नए HEAD में संशोधन करना होगा।


धन्यवाद ग्रेग; 'डिस्क्राइबर्स' से क्या आपका तात्पर्य है कि उन मध्यवर्ती कमिटों को गिट gc द्वारा सफाई के अधीन किया जाता है?
फिलिप

@Phillip हां, इंटरमीडिएट कचरा कचरा के साथ-साथ पुराने HEAD भी बन जाता है क्योंकि इसे HEAD~4इसके माता-पिता के रूप में फिर से लिखा जाता है ।
ग्रेग बेकन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.