स्टेजिंग क्षेत्र में अनकम्यूटेड फ़ाइलों के साथ जीआईटी रीसेट को अनडू करें


109

मैं अपना काम ठीक करने की कोशिश कर रहा हूं। मैंने बेवकूफी की git reset --hard, लेकिन उससे पहले मैंने केवल किया है get add .और नहीं किया है git commit। कृपया सहायता कीजिए! यहाँ मेरा लॉग है:

MacBookPro:api user$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)

#   modified:   .gitignore
...


MacBookPro:api user$ git reset --hard
HEAD is now at ff546fa added new strucuture for api

क्या git reset --hardइस स्थिति में पूर्ववत करना संभव है?


@MarkLongair कमाल का आदमी! आपने अभी-अभी मेरा काम वापस लिया है! मैंने सभी आउटपुट की फाइल बनाने के लिए पायथन स्क्रिप्ट लिखी! मैं पटकथा को उत्तर के रूप
बॉय

4
'मूर्खतापूर्ण' नहीं .. लेकिन 'भोलेपन से' ... क्योंकि मैंने सिर्फ वही किया!
रोजडी कासिम

अभी भी बेवकूफ हो सकता है ;-)
डंकन मैकग्रेगर

यहाँ कैसे इस के कुछ रिवर्स करने के लिए एक महान लेख है । यह कुछ मैनुअल काम करने जा रहा है।
जन स्वरांत

। क्रमबद्ध `` `मेरे लिए काम किया। तिथियां भी दिखाई देने लगती हैं, अंत से ब्लॉब्स की जांच शुरू करें।
ज़ाकी

जवाबों:


175

आपको किसी भी फाइल को वापस प्राप्त करने में सक्षम होना चाहिए जिसे आपने सूचकांक में जोड़ा है (जैसे, आपकी स्थिति में, के साथ git add .) हालांकि यह थोड़ा काम हो सकता है। सूचकांक में एक फ़ाइल जोड़ने के लिए, git इसे ऑब्जेक्ट डेटाबेस में जोड़ता है, जिसका अर्थ है कि इसे इतनी देर तक पुनर्प्राप्त किया जा सकता है क्योंकि कचरा संग्रह अभी तक नहीं हुआ है। जकुब नारुबस्की के जवाब में यह कैसे दिया जाए, इसका एक उदाहरण है:

हालाँकि, मैंने कोशिश की कि एक परीक्षण भंडार पर, और वहाँ कुछ समस्याएं थीं - --cachedहोनी चाहिए --cache, और मैंने पाया कि यह वास्तव में .git/lost-foundनिर्देशिका नहीं बना रही थी । हालाँकि, निम्न चरणों ने मेरे लिए काम किया:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")

यह ऑब्जेक्ट डेटाबेस में सभी ऑब्जेक्ट्स को आउटपुट करना चाहिए जो किसी भी रेफरी द्वारा इंडेक्स में या रीफ्लॉग के माध्यम से पहुंच योग्य नहीं हैं। आउटपुट कुछ इस तरह दिखाई देगा:

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03

... और उनमें से प्रत्येक के लिए, आप कर सकते हैं:

git show 907b308

फ़ाइल की सामग्री को आउटपुट करने के लिए।


बहुत अधिक उत्पादन?

के जवाब में अद्यतन sehe के नीचे टिप्पणी:

यदि आप पाते हैं कि आपके पास उस कमांड से आउटपुट में कई कमिट्स और पेड़ सूचीबद्ध हैं, तो आप आउटपुट से किसी भी ऑब्जेक्ट को हटाना चाहते हैं, जो कि बिना लाइसेंस वाले कॉम्पट से संदर्भित है। (आमतौर पर आप वैसे भी रिफ्लेक्ट के माध्यम से इन कमिट्स पर वापस आ सकते हैं - हम सिर्फ उन वस्तुओं में रुचि रखते हैं जिन्हें इंडेक्स में जोड़ा गया है, लेकिन कभी भी कमिट के माध्यम से नहीं पाया जा सकता है।)

सबसे पहले, कमांड का आउटपुट सेव करें:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > all

अब उन अप्राप्य कमानों के ऑब्जेक्ट नाम के साथ पाया जा सकता है:

egrep commit all | cut -d ' ' -f 3

तो आप केवल उन पेड़ों और वस्तुओं को पा सकते हैं जिन्हें सूचकांक में जोड़ा गया है, लेकिन किसी भी बिंदु पर प्रतिबद्ध नहीं हैं:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") \
  $(egrep commit all | cut -d ' ' -f 3)

यह आपके द्वारा विचार की जाने वाली वस्तुओं की संख्या में भारी कटौती करता है।


अद्यतन: फिलिप ओकले ने विचार करने के लिए वस्तुओं की संख्या में कटौती करने का एक और तरीका सुझाया, जो कि अभी हाल ही में संशोधित फ़ाइलों के तहत विचार करना है .git/objects। आप इनसे मिल सकते हैं:

find .git/objects/ -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort

(मुझे लगता है कि यहाँfind मंगलाचरण मिल गया है ।) उस सूची का अंत इस तरह दिख सकता है:

2011-08-22 11:43:43.0234896770 .git/objects/b2/1700b09c0bc0fc848f67dd751a9e4ea5b4133b
2011-09-13 07:36:37.5868133260 .git/objects/de/629830603289ef159268f443da79968360913a

जिस स्थिति में आप उन वस्तुओं को देख सकते हैं:

git show b21700b09c0bc0fc848f67dd751a9e4ea5b4133b
git show de629830603289ef159268f443da79968360913a

(ध्यान दें कि आपको /ऑब्जेक्ट नाम प्राप्त करने के लिए पथ के अंत में निकालना होगा ।)


इससे पहले कि मैं अपना जवाब पोस्ट करता, मैंने इन चरणों को शामिल करने पर विचार किया। हालाँकि, मेरे एक स्थानीय प्रतिनिधि के साथ ऐसा करने की कोशिश करने पर, मुझे सैकड़ों गैर-जिम्मेदारियाँ मिलीं, और मैं प्रस्तुत किए गए तारीख के अनुसार, उन्हें कहने के लिए पर्याप्त दृष्टिकोण नहीं दे पाया। अब यह कमाल होगा
sehe

3
क्या हाल के समय में आपकी अंतिम प्रतिबद्धताओं की तुलना में सबसे हाल की वस्तुओं के लिए वस्तु समय टिकटों पर एक नज़र रखना संभव नहीं है? या क्या मैं कुछ न कुछ भूल रहा हूं।
फिलिप ओकले

1
@Philip Oakley: उस सुझाव के लिए धन्यवाद, मैंने ऑब्जेक्ट डेटाबेस में सबसे हाल ही में संशोधित वस्तुओं को खोजने के लिए सुझाव जोड़ा है।
मार्क लॉन्गेयर

2
यार, यह कमाल है! जिसने अभी मेरे @ $ $ को बचाया। और मैंने कुछ गित विज्ञान सीखा। बेहतर है कि आप इंडेक्स में क्या जोड़ते हैं ...
bowsersenior

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

58

मैंने सिर्फ एक किया git reset --hardऔर एक प्रतिबद्ध खो दिया। लेकिन मुझे कमिट हैश का पता था, इसलिए मैं git cherry-pick COMMIT_HASHइसे बहाल करने में सक्षम था ।

मैंने कमिट करने के कुछ ही मिनटों में ऐसा किया, इसलिए यह आप में से कुछ के लिए काम कर सकता है।


5
धन्यवाद, धन्यवाद, धन्यवाद इस काम के लिए धन्यवाद, एक दिन काम करने के लिए प्रबंधित
Dace

21
संभवतः यह उल्लेख करने योग्य है कि आप उन हैश का उपयोग कर सकते हैं git reflog, जैसे git reset --hard-> git reflog(HEAD @ {1} हैश को देखते हुए) और अंत मेंgit cherry-pick COMMIT_HASH
जेवियर लोपेज़

2
लोग इसे पढ़ते हैं, सावधान रहें कि यह केवल एक ही प्रतिबद्ध हैश के लिए काम करता है, अगर एक से अधिक प्रतिबद्ध है, तो यह एक ही बार में समस्या का समाधान नहीं करेगा!
ऐन तोवहरी

4
आप वास्तव में "आगे" रीसेट कर सकते हैं। इसलिए यदि आपने कई कमिट पास कर लिए हैं, तो एक और 'git रीसेट - भार <प्रतिबद्ध>' करके उस बिंदु तक पूरी कमिट चेन को रिस्टोर करना चाहिए। (यह देखते हुए कि वे अभी तक GC'ed नहीं हैं)
akimsko

6
पुनर्प्राप्त करने के लिए वन-लाइनर खो गया git reset --hard(यह मानकर कि आपने उस आदेश के बाद और कुछ भी नहीं किया है)git reset --hard @{1}
Ajedi32

13

मार्क लॉन्गेयर के लिए धन्यवाद मुझे अपना सामान वापस मिल गया!

पहले मैंने सभी हैश को एक फ़ाइल में सहेजा:

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") > allhashes

अगली बार मैंने उन सभी को एक सूची में (अप्राप्य बूँद को हटाते हुए) एक सूची में डाल दिया और सभी डेटा को नई फ़ाइलों में डाल दिया ... आपको अपनी फ़ाइलों को चुनना होगा और उन्हें फिर से नाम देना होगा जिसकी आपको आवश्यकता है ... लेकिन मुझे केवल कुछ ही चाहिए files..नहीं यह किसी की मदद करता है ...

commits = ["c2520e04839c05505ef17f985a49ffd42809f",
    "41901be74651829d97f29934f190055ae4e93",
    "50f078c937f07b508a1a73d3566a822927a57",
    "51077d43a3ed6333c8a3616412c9b3b0fb6d4",
    "56e290dc0aaa20e64702357b340d397213cb",
    "5b731d988cfb24500842ec5df84d3e1950c87",
    "9c438e09cf759bf84e109a2f0c18520",
    ...
    ]

from subprocess import call
filename = "file"
i = 1
for c in commits:
    f = open(filename + str(i),"wb")
    call(["git", "show", c],stdout=f)
    i+=1

1
हाँ! मुझे ठीक इसी की आवश्यकता थी। मुझे सभी फाइलों को फिर से बनाने के लिए पायथन स्क्रिप्ट भी पसंद है। अन्य उत्तरों ने मुझे कचरा संग्रह के साथ अपना डेटा खोने के बारे में परेशान कर दिया, इसलिए फाइलों को डंप करना मेरे लिए एक जीत है :)
एरिक ओल्सन

1
मैंने इस उत्तर के आधार पर यह पटकथा लिखी। बॉक्स से बाहर काम करता है: github.com/pendashteh/git-recover-index
एलेक्स

1
मुझे इसे इस तरह से स्वचालित करना आसान लगता है mkdir lost; git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)") | grep -Po '\s\S{40}$' | xargs -i echo "git show {} > lost/{}.blob" | sh:। फाइलें समाप्त हो lost/*.blob
जाएंगी

6

@ टिप्पणियों में Ajedi32 के समाधान ने मेरे लिए बिल्कुल इसी स्थिति में काम किया।

git reset --hard @{1}

ध्यान दें कि ये सभी समाधान कोई git gc नहीं होने पर भरोसा करते हैं, और उनमें से कुछ एक कारण हो सकता है, इसलिए मैं कुछ भी आज़माने से पहले अपनी .it निर्देशिका की सामग्री को ज़िप कर दूंगा ताकि आपके पास स्नैपशॉट वापस आ जाए अगर एक आप के लिए काम नहीं करते।


मेरे पास कई गैर-पंजीकृत फाइलें थीं। फिर मैंने 1 फ़ाइल की सराहना की, और एक किया git reset --hard, जिसने मेरे रेपो को किसी भी अज्ञात फैशन में गड़बड़ कर दिया। @ डंकन, @ {1} क्या करता है? और आप किस टिप्पणी का जिक्र कर रहे हैं? यह एक रीसेट है git reset?
अल्फा_989

मुझे लगता है कि @ {1} अंतिम लेकिन एक प्रतिबद्ध के लिए एक रिश्तेदार संदर्भ है, लेकिन मैं कोई विशेषज्ञ नहीं हूं, सिर्फ रिपोर्टिंग कर रहा हूं कि मेरे लिए क्या काम किया है
डंकन मैक्ग्रेगर

3

एक ही मुद्दे में भाग गया, लेकिन सूचकांक में परिवर्तन नहीं जोड़ा गया था। इसलिए उपरोक्त सभी आदेशों ने मुझे वांछित बदलाव वापस नहीं लाए।

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

निराशा में, मैंने अपने संपादक (लाइटटेबल) में सीटीआरएल-जेड को दबाने की कोशिश की, हर खुले टैब में एक बार - यह सौभाग्य से उस टैब में फ़ाइल को पुनर्प्राप्त करता है, जिसकी नवीनतम स्थिति से पहले git reset --hard। HTH।


1
बिल्कुल वैसी ही स्थिति, इंडेक्स में जोड़ने से चूक गई और हार्ड रीसेट किया और किसी भी समाधान से ऊपर काम नहीं किया। यह एक स्मार्ट चाल थी, धन्यवाद मैंने Ctrl + Z किया और अपना दिन बचाया। मेरा संपादक: SublimeText एक मेरी तरफ से!
विवेक

1

यह संभवत: वहाँ से बाहर निकलने वाले पेशेवरों के लिए स्पष्ट है, लेकिन मैं इसे अपनी उन्मत्त खोज में डालना चाहता था क्योंकि मैंने इसे लाया नहीं था।

मैंने कुछ फाइलों का मंचन किया, और एक किया git reset --hard, थोड़ा बाहर किया, और फिर देखा कि मेरी स्थिति ने दिखाया कि मेरी सभी फाइलें अभी भी मंचित हैं और साथ ही साथ उनके सभी डिलीट भी अनस्टेंड हैं।

इस बिंदु पर आप उन परिवर्तनों को कर सकते हैं, जब तक आप उनके विलोपन को चरणबद्ध नहीं करते हैं। इसके बाद, आपको केवल git reset --hardएक और समय करने के लिए साहस करना होगा, जो आपको उन परिवर्तनों को वापस लाएगा जिन्हें आपने मंचित किया था और अब वे प्रतिबद्ध हैं।

फिर, यह शायद कुछ भी नया नहीं है, लेकिन मैं उम्मीद कर रहा हूं कि चूंकि इससे मुझे मदद मिली और मुझे यह सुझाव देने में कुछ भी नहीं मिला, इसलिए यह किसी और की मदद कर सकता है।


1

अच्छाई, मैंने अपने बालों को तब तक खींचा जब तक कि मैं इस सवाल और उसके जवाब में नहीं भाग गया। मेरा मानना ​​है कि पूछे गए प्रश्न का सही और संक्षिप्त जवाब उपलब्ध है, यदि आप दो टिप्पणियों को एक साथ ऊपर खींचते हैं, तो यहां यह सब एक ही स्थान पर है:

  1. जैसा कि chilicuil द्वारा उल्लेख किया गया है, git reflogवहां उस हैश को पहचानने के लिए चलाएं जिसे आप वापस प्राप्त करना चाहते हैं

  2. जैसा कि akimsko द्वारा बताया गया है, आप तब तक चेरी पिक नहीं करना चाहेंगे जब तक कि आप केवल एक कमिट नहीं खोते हैं, इसलिए आपको दौड़ना चाहिए git reset --hard <hash-commit-you-want>

एग्लिट ​​ग्रहण करने वालों के लिए ध्यान दें: मुझे एग्लिट ​​के साथ इन चरणों को करने का कोई तरीका नहीं मिला। एक्लिप्स को बंद करना, टर्मिनल विंडो से ऊपर की कमांड चलाना, और फिर एक्लिप्स को फिर से खोलना मेरे लिए ठीक काम करता है।


0

हालांकि, उपरोक्त समाधान काम कर सकते हैं, हालांकि, gitजटिल पूर्ववत के माध्यम से जाने के बजाय इससे उबरने के सरल तरीके हैं । मुझे लगता है कि अधिकांश गिट-रीसेट फ़ाइलों की एक छोटी संख्या पर होते हैं, और यदि आप पहले से ही वीआईएम का उपयोग करते हैं, तो यह सबसे अधिक समय का समाधान हो सकता है। चेतावनी यह है कि आपको पहले से ही ViM'sनिरंतर-पूर्ववत उपयोग करना चाहिए , जिसे आपको किसी भी तरह से उपयोग करना चाहिए, क्योंकि यह आपको असीमित संख्या में परिवर्तनों को पूर्ववत करने की क्षमता प्रदान करता है।

यहाँ कदम हैं:

  1. Vim प्रेस में :और कमांड टाइप करें set undodir। यदि आप अपने आप को persistent undoचालू कर चुके हैं .vimrc, तो यह एक समान परिणाम दिखाएगा undodir=~/.vim_runtime/temp_dirs/undodir

  2. अपने रेपो उपयोग git logमें अंतिम तिथि / समय का पता लगाने के लिए जिसे आपने अंतिम प्रतिबद्ध बनाया था

  3. अपने शेल में अपने undodirउपयोग के लिए नेविगेट करें cd ~/.vim_runtime/temp_dirs/undodir

  4. इस निर्देशिका में इस कमांड का उपयोग उन सभी फाइलों को खोजने के लिए किया जाता है जिन्हें आपने अंतिम प्रतिबद्ध के बाद बदल दिया है

    find . -newermt "2018-03-20 11:24:44" \! -newermt "2018-03-23" \( -type f -regextype posix-extended -regex '.*' \) \-not -path "*/env/*" -not -path "*/.git/*"

    यहाँ "2018-03-20 11:24:44" अंतिम प्रतिबद्ध की तारीख और समय है। यदि आपने जिस तारीख git reset --hardको "2018-03-22" किया है, तो "2018-03-22" का उपयोग करें, फिर "2018-03-22" का उपयोग करें। यह एक खोज के कारण है, जहां निचली सीमा समावेशी है, और ऊपरी सीमा अनन्य है। https://unix.stackexchange.com/a/70404/242983

  5. अगली फ़ाइलों में से प्रत्येक पर जाएं उन्हें vim में खोलें, और "पहले 20 मी" करें। आप "h पहले" का उपयोग करके "पहले" के बारे में अधिक जानकारी प्राप्त कर सकते हैं। यहां earlier 20m20 मिनट पहले फाइल की स्थिति पर वापस जाने का मतलब है कि आपने git hard --reset20 मिनट पहले किया था। इसे उन सभी फाइलों पर दोहराएं, जिन्हें findकमांड से अलग किया गया था। मुझे यकीन है कि कोई व्यक्ति एक स्क्रिप्ट लिख सकता है जो इन चीजों को संयोजित करेगा।


0

मैं IntelliJ का उपयोग कर रहा हूं और बस प्रत्येक फ़ाइल के माध्यम से जाने और करने में सक्षम था:

Edit -> reload from disk

सौभाग्य से, मैंने git statusअपने काम के बदलावों को मिटाने से ठीक पहले किया था , इसलिए मुझे पता था कि मुझे क्या करना है।


0

अपनी फ़ाइल पदानुक्रम को याद रखना और फिल ओक्ले संशोधन के साथ मार्क लॉन्गेयर की तकनीक का उपयोग नाटकीय परिणाम देता है।

अनिवार्य रूप से यदि आपने कम से कम फ़ाइलों को रेपो में जोड़ा है, लेकिन इसे प्रतिबद्ध नहीं किया है, तो आप अंतःक्रियात्मक रूप से उपयोग करके पुनर्स्थापित कर सकते हैं git show, लॉग का निरीक्षण कर सकते हैं और प्रत्येक फ़ाइल बनाने के लिए शेल पुनर्निर्देशन का उपयोग कर सकते हैं (आपकी रुचि के पथ को याद करते हुए)।

HTH!


0

यदि आपने हाल ही में समीक्षा की है, git diffतो इस तरह की घटनाओं से उबरने के लिए एक और तरीका है, भले ही आपने अभी तक परिवर्तनों का मंचन नहीं किया है: यदि उत्पादन git diffअभी भी आपके कंसोल बफर में है, तो आप बस स्क्रॉल कर सकते हैं, कॉपी-पेस्ट कर सकते हैं एक फ़ाइल patchमें अंतर करें और अपने पेड़ में अंतर लागू करने के लिए उपकरण का उपयोग करें patch -p0 < file:। इस दृष्टिकोण ने मुझे कुछ समय बचाया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.