Git रिपॉजिटरी में करंट को केवल (प्रारंभिक) कमिट करें?


664

वर्तमान में मेरे पास एक स्थानीय Git रिपॉजिटरी है, जिसे मैं एक Github रिपॉजिटरी में धकेलता हूं।

स्थानीय रिपॉजिटरी में ~ 10 कमिट हैं, और जीथब रिपॉजिटरी इस की एक सिंक्रनाइज़ डुप्लिकेट है।

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

मैं फिर इन परिवर्तनों को Github पर धकेलना चाहूंगा।

मैंने गिट रीबेस की जांच की है, लेकिन यह विशिष्ट संस्करणों को हटाने के लिए अधिक अनुकूल प्रतीत होता है। एक और संभावित समाधान स्थानीय रेपो को हटाना है, और एक नया बनाना है - हालांकि यह शायद बहुत काम पैदा करेगा!

ईटीए: विशिष्ट निर्देशिका / फाइलें हैं जो अनट्रैक हैं - यदि संभव हो तो मैं इन फाइलों के अनट्रैकिंग को बनाए रखना चाहूंगा।


6
यह भी देखें stackoverflow.com/questions/435646/… ("मैं एक Git रिपॉजिटरी के पहले दो
कमेंट्स को


जवाबों:


981

यहाँ जानवर-बल दृष्टिकोण है। यह रिपॉजिटरी के कॉन्फ़िगरेशन को भी हटा देता है।

नोट : यह काम नहीं करता है यदि रिपॉजिटरी में सबमॉड्यूल हैं! यदि आप सबमॉड्यूल्स का उपयोग कर रहे हैं, तो आपको उदाहरण के लिए इंटरएक्टिव रिबेस का उपयोग करना चाहिए

चरण 1: सभी इतिहास को हटा दें ( सुनिश्चित करें कि आपके पास बैकअप है, इसे वापस नहीं किया जा सकता है )

cat .git/config  # note <github-uri>
rm -rf .git

चरण 2: केवल वर्तमान सामग्री के साथ गिट रेपो का पुनर्निर्माण करें

git init
git add .
git commit -m "Initial commit"

चरण 3: गिटहब को धक्का दें।

git remote add origin <github-uri>
git push -u --force origin master

3
धन्यवाद लार्समैन - मैंने इसे अपने समाधान के रूप में उपयोग करने का विकल्प चुना है। हालांकि Git रेपो को आरंभीकृत करने से पुराने रेपो में अनुपयोगी फ़ाइलों का रिकॉर्ड खो जाता है, यह शायद मेरी समस्या का एक सरल समाधान है।
कास

5
@ उके: मुझे लगता है कि आपके .gitignoreउन, सही संभालना चाहिए?
फ्रेड फू

48
अपने .it / config को पहले सहेजें, और बाद में पुनर्स्थापित करें।
lalebarde

@lalebarde यदि आप .git / config को पुनर्स्थापित git commit -m "Initial commit"करते हैं, तो आप शायद उस git remote add ...हिस्से को छोड़ सकते हैं , यह मानते हुए कि वह आपके config में पहले से था, और सीधे पुश करने के लिए आगे बढ़ें। इसने मेरे लिए काम किया।
बुटेल बटुकस 3

24
यदि आप संवेदनशील डेटा को निकालने का प्रयास कर रहे हैं, तो इससे सावधान रहें: नई पुश की गई मास्टर ब्रांच में केवल एक ही कमिटमेंट की मौजूदगी भ्रामक है - इतिहास अभी भी मौजूद होगा, यह सिर्फ उस ब्रांच से एक्सेस नहीं होगा। यदि आपके पास टैग हैं, उदाहरण के लिए, जो पुराने कमिट्स की ओर इशारा करते हैं, तो ये कमिट सुलभ होंगे। वास्तव में, जिट फू के एक बिट के साथ किसी के लिए, मुझे यकीन है कि इस धक्का धक्का के बाद, वे अभी भी गिटहब भंडार से सभी इतिहास को पुनर्प्राप्त करने में सक्षम होंगे - और यदि आपके पास अन्य शाखाएं या टैग हैं, तो वे नहीं करते हैं यहाँ तक कि बहुत फू फू की जरूरत है।
रॉबर्ट मुइल

621

एकमात्र समाधान जो मेरे लिए काम करता है (और सबमोडुल्स को काम करता है)

git checkout --orphan newBranch
git add -A  # Add all files and commit them
git commit
git branch -D master  # Deletes the master branch
git branch -m master  # Rename the current branch to master
git push -f origin master  # Force push master branch to github
git gc --aggressive --prune=all     # remove the old files

.git/जब मेरे पास सबमॉडल्स होते हैं, तो हमेशा हटाने से बहुत बड़ी समस्या होती है। उपयोग git rebase --rootकरने से किसी तरह मेरे लिए संघर्ष हो जाएगा (और जब से मेरा इतिहास रहा है)।


55
यह सही उत्तर होना चाहिए! बस git push -f origin masterपिछले ऑप के रूप में जोड़ें और सूरज आपके ताजा रेपो पर फिर से चमक जाएगा! :)
gru

2
क्या यह पुराने कमिट्स को आसपास नहीं रखता है?
ब्रैड

4
@JonePolvora git fetch; Git रीसेट --hard मूल / मास्टर stackoverflow.com/questions/4785107/...
गूंज

5
ऐसा करने के बाद, रेपो मुक्त स्थान होगा?
inuart

8
मेरा मानना ​​है कि आपको अपने उत्तर के लिए अंतिम पंक्ति के रूप में @ जैसनगोमाट का सुझाव जोड़ना चाहिए। git gc --aggressive --prune allइतिहास खोने के पूरे बिंदु के बिना याद किया जाएगा।
टुनके गोनकुओलू

93

यह मेरा पसंदीदा तरीका है:

git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})

यह एक प्रतिबद्ध के साथ एक नई शाखा बनाएगा जो HEAD में सब कुछ जोड़ता है। यह किसी और चीज़ में बदलाव नहीं करता है, इसलिए यह पूरी तरह से सुरक्षित है।


3
सबसे अच्छा दृष्टिकोण! साफ़ करो, और काम करो। इसके अतिरिक्त, मैं "मास्टर" से "स्थानीय-कार्य" और "new_branch_name" से "मास्टर" में बहुत सारे परिवर्तनों के साथ शाखा का नाम बदल देता हूं। मास्टर में, निम्नलिखित करें: git -m स्थानीय-परिवर्तन git शाखा -m स्थानीय-परिवर्तन git चेकआउट new_branch_name git शाखा -m मास्टर <
Valtoni Boaventura

यह वास्तव में छोटा और चिकना दिखता है, केवल एक चीज जिसे मैं नहीं समझता या अभी तक नहीं देखा है वह है HEAD ^ {पेड़}, क्या कोई समझा सकता है? इसके अलावा मैंने इसे "दिए गए कमिट से नई शाखा बनाएं", ___ से दिए गए कमिट-मैसेज के साथ एक नई कमिट-ऑब्जेक्ट
बनाकर पढ़ा है

3
Git संदर्भ वाक्यविन्यास के बारे में प्रश्नों के उत्तर देखने के लिए निश्चित स्थान git-rev-parseडॉक्स में है। यहां जो हो रहा है, उसके git-commit-treeलिए एक पेड़ (रेपो के एक स्नैपशॉट) के संदर्भ की आवश्यकता है, लेकिन HEADएक संशोधन है। एक प्रतिबद्ध से जुड़े पेड़ को खोजने के लिए हम <rev>^{<type>}फॉर्म का उपयोग करते हैं ।
dan_waterworth

अच्छा उत्तर। अच्छा काम करता है। अंत में कहते हैंgit push --force <remote> new_branch_name:<remote-branch>
फेलिप अल्वारेज़

31

दूसरा विकल्प, जो आपके बहुत काम आ सकता है अगर आपके पास बहुत सारे काम हैं, तो एक इंटरैक्टिव रिबेस है (मान लीजिए कि आपका git संस्करण है> = = 1.7.12):git rebase --root -i

जब आपके संपादक की सूची प्रस्तुत की जाती है:

  • पहले कमिट के लिए "पिक" को "रीवर्ड" में बदलें
  • हर दूसरे कमिट में "पिक" को "फिक्सअप" में बदलें

सहेजें और बंद करें। गिट रिबास करना शुरू कर देगा।

अंत में आपके पास एक नया रूट कमिट होगा जो कि इसके बाद आए सभी लोगों का एक संयोजन है।

फायदा यह है कि आपको अपनी रिपॉजिटरी को डिलीट करने की जरूरत नहीं है और अगर आपके पास दूसरे विचार हैं तो आपको हमेशा कमबैक करना होगा।

यदि आप वास्तव में अपने इतिहास को बनाना चाहते हैं, तो इस प्रतिबद्ध के लिए मास्टर को रीसेट करें और अन्य सभी शाखाओं को हटा दें।


error: failed to push some refs to
रिबास

@Begueradj यदि आपने पहले ही उस शाखा को धक्का दे दिया है जिसे आपने विद्रोह किया है, तो आपको धक्का देने की आवश्यकता होगी git push --force-with-lease। बल-के साथ-पट्टे का उपयोग किया जाता है क्योंकि यह --force से कम विनाशकारी होता है।
कार्ल

19

लारसमैन की प्रस्तावित विधि का वेरिएंट :

अपनी अनट्रैकफ़ाइल्स सूची सहेजें:

git ls-files --others --exclude-standard > /tmp/my_untracked_files

अपना गिट कॉन्फ़िगरेशन सहेजें:

mv .git/config /tmp/

इसके बाद लार्समैन का पहला चरण करें:

rm -rf .git
git init
git add .

अपने कॉन्‍फ़िगर को पुनर्स्थापित करें:

mv /tmp/config .git/

आपको अनट्रैक की गई फ़ाइलों को अनट्रैक करें:

cat /tmp/my_untracked_files | xargs -0 git rm --cached

फिर प्रतिबद्ध:

git commit -m "Initial commit"

और अंत में अपने भंडार में धकेलें:

git push -u --force origin master

6

नीचे एक स्क्रिप्ट @Zeelot के उत्तर से अनुकूलित है। इसे सभी शाखाओं से इतिहास को हटा देना चाहिए, न कि केवल गुरु शाखा को:

for BR in $(git branch); do   
  git checkout $BR
  git checkout --orphan ${BR}_temp
  git commit -m "Initial commit"
  git branch -D $BR
  git branch -m $BR
done;
git gc --aggressive --prune=all

इसने मेरे उद्देश्यों के लिए काम किया (मैं सबमॉड्यूल का उपयोग नहीं कर रहा हूं)।


4
मुझे लगता है कि आप प्रक्रिया को पूरा करने के लिए पुश मास्टर को मजबूर करना भूल गए।
not2qubit

2
मुझे थोड़ा संशोधन करना पड़ा। git branchआपकी जाँच की गई शाखा के आगे एक तारांकन चिह्न शामिल होगा, जिसे तब ग्लोब किया जाएगा, जिससे यह सभी फ़ाइलों या फ़ोल्डरों को हल करने के लिए होगा जैसे कि वे शाखा नाम भी थे। इसके बजाय, मैंने इस्तेमाल git branch --format="%(refname:lstrip=2)"किया जिसने मुझे सिर्फ शाखा नाम दिए।
बेन रिचर्ड्स

@ not2qubit: इसके लिए धन्यवाद। सटीक कमांड क्या होगा? git push --force origin master, या git push --force-with-lease? स्पष्ट रूप से उत्तरार्द्ध सुरक्षित है (देखें stackoverflow.com/questions/5509543/… )
Shafique Jamal

@BenRichards। दिलचस्प। मैं इसे फिर से एक फ़ोल्डर के साथ कुछ बिंदु पर आज़माऊंगा जो इसे जांचने के लिए एक शाखा नाम से मेल खाता है, फिर उत्तर को अपडेट करें। धन्यवाद।
शैफिक जमाल

5

आप उथले क्लोनों का उपयोग कर सकते हैं (git> 1.9):

git clone --depth depth remote-url

आगे पढ़े: http://blogs.atlassian.com/2014/05/handle-big-repositories-git/


4
इस तरह के क्लोन को नए भंडार में नहीं धकेला जा सकता है।
सेवेर्न नीमिएक

1
यह जानना उपयोगी होगा कि उस सीमा को कैसे कम किया जाए। क्या कोई समझा सकता है कि इसे बलपूर्वक क्यों नहीं धकेला जा सकता है?
8

आपके सवाल का जवाब: stackoverflow.com/questions/6900103/…
माथियास एम

4

git filter-branch प्रमुख सर्जरी उपकरण है।

git filter-branch --parent-filter true -- @^!

--parent-filterमाता-पिता को स्टैडेन पर मिलता है और स्टडआउट पर फिर से लिखे गए माता-पिता को प्रिंट करना चाहिए; यूनिक्स trueसफलतापूर्वक बाहर निकलता है और कुछ भी नहीं छापता है, इसलिए: कोई माता-पिता नहीं। @^!है Git के लिए आशुलिपि "सिर के लिए प्रतिबद्ध है, लेकिन इसके माता-पिता में से किसी न"। फिर अन्य सभी रेफरी को हटा दें और अवकाश पर धक्का दें।


3

बस Github रेपो को हटा दें और एक नया बनाएं। अब तक का सबसे तेज, सबसे आसान और सबसे सुरक्षित तरीका। आखिरकार, आपको उन सभी कमांडों को स्वीकार किए गए समाधान में ले जाने की क्या ज़रूरत है जब आप चाहते हैं कि एक एकल प्रतिबद्ध के साथ मास्टर शाखा है?


1
मुख्य बिंदुओं में से एक को यह देखने में सक्षम होना है कि इसे कहाँ से कांटा गया था।
not2qubit

मैंने अभी यह किया है और यह ठीक है
thanos.a

2

नीचे दी गई विधि बिल्कुल प्रतिलिपि प्रस्तुत करने योग्य है, इसलिए दोनों पक्षों के अनुरूप होने पर फिर से क्लोन चलाने की आवश्यकता नहीं है, बस स्क्रिप्ट को दूसरी तरफ भी चलाएं।

git log -n1 --format=%H >.git/info/grafts
git filter-branch -f
rm .git/info/grafts

यदि आप इसे साफ़ करना चाहते हैं, तो इस स्क्रिप्ट को आज़माएँ:

http://sam.nipl.net/b/git-gc-all-ferocious

मैंने एक स्क्रिप्ट लिखी जो रिपॉजिटरी की प्रत्येक शाखा के लिए "इतिहास को मारती है":

http://sam.nipl.net/b/git-kill-history

इसे भी देखें: http://sam.nipl.net/b/confirm


1
इसके लिए धन्यवाद। बस FYI करें: प्रत्येक शाखा के लिए इतिहास को मारने के लिए आपकी स्क्रिप्ट कुछ अद्यतन का उपयोग कर सकती है - यह निम्नलिखित त्रुटियां देता है: git-hash: not foundऔरSupport for <GIT_DIR>/info/grafts is deprecated
Shafique Jamal

1
@ शफ़ीक़ जमाल, धन्यवाद, छोटी "git-hash" स्क्रिप्ट है git log HEAD~${1:-0} -n1 --format=%H, यहाँ, sam.aiki.info/b/git-hash यह बेहतर होगा कि सार्वजनिक उपभोग के लिए इसे एक स्क्रिप्ट में रखा जाए। अगर मैं कभी भी इसे फिर से उपयोग करता हूं, तो मैं यह पता लगा सकता हूं कि "ग्राफ्ट्स" को बदलने वाले नए फीचर के साथ यह कैसे करना है।
सैम वाटकिंस

2

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

एक अधिक वैचारिक उत्तर:

अगर कोई टैग / शाखाएँ / रेफरी उन्हें इंगित नहीं करता है तो git स्वचालित रूप से कचरा इकट्ठा करता है। तो आपको बस सभी टैग / शाखाओं को हटाना होगा और एक नया अनाथ प्रतिबद्ध बनाना होगा, किसी भी शाखा से जुड़े - सम्मेलन द्वारा आप शाखा masterको उस बिंदु पर जाने देंगे ।

पुराने, अगम्य कमिट्स तब तक फिर कभी किसी को दिखाई नहीं देंगे जब तक कि वे निम्न-स्तरीय गिट कमांड के साथ खुदाई नहीं करते। यदि आपके लिए यह पर्याप्त है, तो मैं बस वहीं रुक जाऊंगा और जब भी चाहे, स्वचालित जीसी को काम करने देगा। यदि आप उनसे तुरंत छुटकारा पाना चाहते हैं, तो आप git gc(संभवतः के साथ --aggressive --prune=all) उपयोग कर सकते हैं । दूरस्थ गिट रिपॉजिटरी के लिए, जब तक आपके पास उनके फ़ाइल सिस्टम तक शेल पहुंच नहीं है, तब तक आपके पास कोई रास्ता नहीं है।


इसके अलावा, @Zeelot के उत्तर के संदर्भ में देखा जाए तो अच्छा है।
मोगेन्स ट्रैशरडाक

यूप, ज़ीलोट की आज्ञाएं हैं जो मूल रूप से ऐसा करते हैं (बस पूरी तरह से शुरू करके, जो ओपी के लिए ठीक हो सकता है)। @MogensTrasherDK
AnoE

0

हेयर यू गो:

#!/bin/bash
#
# By Zibri (2019)
#
# Usage: gitclean username password giturl
#
gitclean () 
{ 
    odir=$PWD;
    if [ "$#" -ne 3 ]; then
        echo "Usage: gitclean username password giturl";
        return 1;
    fi;
    temp=$(mktemp -d 2>/dev/null /dev/shm/git.XXX || mktemp -d 2>/dev/null /tmp/git.XXX);
    cd "$temp";
    url=$(echo "$3" |sed -e "s/[^/]*\/\/\([^@]*@\)\?\.*/\1/");
    git clone "https://$1:$2@$url" && { 
        cd *;
        for BR in "$(git branch|tr " " "\n"|grep -v '*')";
        do
            echo working on branch $BR;
            git checkout $BR;
            git checkout --orphan $(basename "$temp"|tr -d .);
            git add -A;
            git commit -m "Initial Commit" && { 
                git branch -D $BR;
                git branch -m $BR;
                git push -f origin $BR;
                git gc --aggressive --prune=all
            };
        done
    };
    cd $odir;
    rm -rf "$temp"
}

यहाँ भी होस्ट किया गया: https://gist.github.com/Zibri/76614988478a076bbe105545a16ee743


गाह! मुझे कमांड लाइन पर अपना अप्रमाणित, असुरक्षित पासवर्ड प्रदान न करें! इसके अलावा, git शाखा का आउटपुट आम तौर पर स्क्रिप्टिंग के लिए खराब अनुकूल है। आप प्लंबिंग टूल्स को देखना चाह सकते हैं।
डी। बेन नोबल

-1

मैंने .gitअपनी परियोजना से सिर्फ फ़ोल्डर को हटाकर और IntelliJ के माध्यम से संस्करण नियंत्रण के साथ पुनः स्थापित करके इसी तरह की समस्या को हल किया । नोट: .gitफ़ोल्डर छिपा हुआ है। आप इसे टर्मिनल में देख सकते हैं ls -a, और फिर इसका उपयोग करके हटा सकते हैं rm -rf .git


वह कदम 1 में क्या कर रहा है: rm -rf .git?
रातें

-1

इसके लिए Shallow Clone कमांड git क्लोन --depth 1 URL का उपयोग करें - यह केवल रिपॉजिटरी के वर्तमान हेड का क्लोन करेगा


-2

पिछले कमिट को git से हटाने के लिए, आप बस चला सकते हैं

git reset --hard HEAD^ 

यदि आप ऊपर से कई कमियाँ निकाल रहे हैं, तो आप चला सकते हैं

git reset --hard HEAD~2 

पिछले दो कमिट्स को हटाने के लिए। और भी कमियाँ निकालने के लिए आप संख्या बढ़ा सकते हैं।

अधिक जानकारी यहाँ।

Git tutoturial यहाँ रिपॉजिटरी को शुद्ध करने में मदद प्रदान करता है:

आप फ़ाइल को इतिहास से हटाना चाहते हैं और इसे .gitignore में जोड़ना सुनिश्चित करते हैं कि यह गलती से फिर से प्रतिबद्ध नहीं है। हमारे उदाहरण के लिए, हम GitHub मणि भंडार से Rakefile को निकालने जा रहे हैं।

git clone https://github.com/defunkt/github-gem.git

cd github-gem

git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch Rakefile' \
  --prune-empty --tag-name-filter cat -- --all

अब जब हमने फ़ाइल को इतिहास से मिटा दिया है, तो सुनिश्चित करें कि हम गलती से इसे फिर से न करें।

echo "Rakefile" >> .gitignore

git add .gitignore

git commit -m "Add Rakefile to .gitignore"

यदि आप रिपॉजिटरी की स्थिति से खुश हैं, तो आपको दूरस्थ रिपॉजिटरी को अधिलेखित करने के लिए परिवर्तनों को बल देने की आवश्यकता है।

git push origin master --force

6
फ़ाइलों को निकालें या रिपॉजिटरी से आने से सवाल का कोई संबंध नहीं है (जो इतिहास को हटाने के लिए कहता है, एक पूरी तरह से अलग बात है)। ओपी एक स्वच्छ इतिहास चाहता है लेकिन भंडार की वर्तमान स्थिति को संरक्षित करना चाहता है।
विक्टर श्रोडर

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