হার্ড ডিস্ক ব্যর্থতায় ক্ষতিগ্রস্থ গিট অবজেক্টগুলি কীভাবে পুনরুদ্ধার করবেন?


92

আমার একটি হার্ড ডিস্ক ব্যর্থ হয়েছে যার ফলস্বরূপ একটি গিট সংগ্রহস্থলের কিছু ফাইল ক্ষতিগ্রস্থ হয়েছে। চলমান অবস্থায় git fsck --fullআমি নিম্নলিখিত আউটপুটটি পাই:

error: .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack SHA1 checksum mismatch
error: index CRC mismatch for object 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid code lengths set)
error: cannot unpack 6c8cae4994b5ec7891ccb1527d30634997a978ee from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack at offset 97824129
error: inflate: data stream error (invalid stored block lengths)
error: failed to read object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa at offset 276988017 from .git/objects/pack/pack-6863e0a0e4b4ded6090fac5d12eba6ca7346b19c.pack
fatal: object 0dcf6723cc69cc7f91d4a7432d0f1a1f05e77eaa is corrupted

আমার কাছে সংগ্রহস্থলের ব্যাকআপ রয়েছে তবে প্যাক ফাইলটি অন্তর্ভুক্ত থাকা একমাত্র ব্যাকআপের এটি ইতিমধ্যে ক্ষতিগ্রস্থ হয়েছে। সুতরাং আমি মনে করি যে আমাকে বিভিন্ন ব্যাকআপ থেকে একক জিনিস পুনরুদ্ধার করার উপায় খুঁজে বের করতে হবে এবং গিটকে কেবল সঠিক অবজেক্ট সহ একটি নতুন প্যাক তৈরির নির্দেশ দিতে হবে।

আপনি কি আমাকে আমার সংগ্রহস্থল ঠিক করতে ইঙ্গিত দিতে পারেন?


4
এই মাত্র আমার ঘটেছে। আমি গিটার অবজেক্টগুলির সাথে ঝামেলা করতে চাই না ... সুতরাং রিমোট রিপোজিটরি থেকে প্রকল্পটিকে নতুন ফোল্ডারে পুনরায় ক্লোন করুন এবং তারপরে আমার সমস্যাযুক্ত সংগ্রহস্থলগুলি ( .gitঅবশ্যই ফোল্ডার বাদে ) সমস্ত ফাইলের সতেজ ক্লোন করা রেপিতে অনুলিপি করুন ... এবং তারপরে git statusনতুন রেপোতে ... গিটটি আমার ফাইলগুলিতে সমস্ত প্রভাবিত পরিবর্তনগুলি সঠিকভাবে সনাক্ত করে এবং আমি আবার আমার কাজ শুরু করতে পারি।
রোসদী কাসিম

উত্তর:


82

পূর্ববর্তী কিছু ব্যাকআপগুলিতে, আপনার খারাপ জিনিসগুলি বিভিন্ন ফাইলে প্যাক করা থাকতে পারে বা আলগা বস্তু হতে পারে। সুতরাং আপনার জিনিস পুনরুদ্ধার হতে পারে।

দেখে মনে হচ্ছে আপনার ডাটাবেসে কয়েকটি খারাপ জিনিস রয়েছে। সুতরাং আপনি এটি ম্যানুয়াল উপায়ে করতে পারে।

কারণগুলি git hash-object, git mktreeএবং git commit-treeপ্যাকগুলিতে পাওয়া যায় বলে বস্তুগুলি লিখবেন না, তারপরে এটি শুরু করুন:

mv .git/objects/pack/* <somewhere>
for i in <somewhere>/*.pack; do
  git unpack-objects -r < $i
done
rm <somewhere>/*

(আপনার প্যাকগুলি সংগ্রহশালা থেকে সরিয়ে নেওয়া হয়েছে এবং এতে আবার প্যাক করা হয়নি; কেবলমাত্র ভাল বস্তু এখন ডাটাবেসে রয়েছে)

আপনি করতে পারেন:

git cat-file -t 6c8cae4994b5ec7891ccb1527d30634997a978ee

এবং অবজেক্টের ধরণটি পরীক্ষা করে দেখুন।

যদি টাইপটি ব্লব হয়: পূর্ববর্তী ব্যাকআপগুলি থেকে ফাইলের সামগ্রীগুলি পুনরুদ্ধার করুন ( git showবা এর সাথে git cat-fileবা git unpack-file;) তবে git hash-object -wআপনার বর্তমান সংগ্রহস্থলে বস্তুটি পুনরায় লেখতে হতে পারে।

প্রকারটি যদি গাছ হয়: আপনি git ls-treeআগের ব্যাকআপগুলি থেকে গাছটি পুনরুদ্ধার করতে পারেন ; তারপর git mktreeআপনার বর্তমান সংগ্রহস্থলের মধ্যে আবার লিখতে।

প্রকারটি যদি প্রতিশ্রুতিবদ্ধ হয়: সাথে একই git show, git cat-fileএবং git commit-tree

অবশ্যই, আমি এই প্রক্রিয়াটি শুরু করার আগে আপনার মূল কাজের অনুলিপিটিকে ব্যাকআপ করব।

এছাড়াও, দুর্নীতিগ্রস্থ ব্লব অবজেক্টটি কীভাবে পুনরুদ্ধার করবেন তা একবার দেখুন ।


4
ধন্যবাদ, সে আমাকে বাঁচিয়েছে! আমি আমার সঠিক পদক্ষেপগুলি পৃথক উত্তর হিসাবে পোস্ট করব।
খ্রিস্টান

কেবল একটি সংশোধন: "সমাপ্ত" দিয়ে শেষ হওয়ার জন্য আদেশটি "শেষ" নয়।
ফিলিপ

আমি এটি করার চেষ্টা করছি তবে .git/objects/pack/খালি
kirill_igum

আমার জন্য একটি; গিট আনপ্যাক-অবজেক্টগুলির পরে নিখোঁজ ছিল
ith

@ মিথরন্দির: আপনি যদি আগের লাইনে 'সম্পন্ন' রাখেন: হ্যাঁ, আপনার একটি সেমিকোলন দরকার। আমি যা লিখেছিলাম তা যদি আপনি টাইপ করেন তবে আপনি করবেন না।
ড্যানিয়েল ফানজুল

38

বানেনগাস্ক আমাকে সঠিক ট্র্যাকের উপরে রাখছিল । আরও রেফারেন্সের জন্য, আমি আমার সংগ্রহস্থল দুর্নীতির সমাধান করতে যে পদক্ষেপ নিয়েছি তা পোস্ট করতে চাই। পুরানো প্যাকগুলিতে বা সংগ্রহশালা ব্যাকআপগুলিতে প্রয়োজনীয় সমস্ত জিনিস খুঁজে পাওয়ার জন্য আমি যথেষ্ট ভাগ্যবান ছিলাম।

# Unpack last non-corrupted pack
$ mv .git/objects/pack .git/objects/pack.old
$ git unpack-objects -r < .git/objects/pack.old/pack-012066c998b2d171913aeb5bf0719fd4655fa7d0.pack
$ git log
fatal: bad object HEAD

$ cat .git/HEAD 
ref: refs/heads/master

$ ls .git/refs/heads/

$ cat .git/packed-refs 
# pack-refs with: peeled 
aa268a069add6d71e162c4e2455c1b690079c8c1 refs/heads/master

$ git fsck --full 
error: HEAD: invalid sha1 pointer aa268a069add6d71e162c4e2455c1b690079c8c1
error: refs/heads/master does not point to a valid object!
missing blob 75405ef0e6f66e48c1ff836786ff110efa33a919
missing blob 27c4611ffbc3c32712a395910a96052a3de67c9b
dangling tree 30473f109d87f4bcde612a2b9a204c3e322cb0dc

# Copy HEAD object from backup of repository
$ cp repobackup/.git/objects/aa/268a069add6d71e162c4e2455c1b690079c8c1 .git/objects/aa
# Now copy all missing objects from backup of repository and run "git fsck --full" afterwards
# Repeat until git fsck --full only reports dangling objects

# Now garbage collect repo
$ git gc
warning: reflog of 'HEAD' references pruned commits
warning: reflog of 'refs/heads/master' references pruned commits
Counting objects: 3992, done.
Delta compression using 2 threads.
fatal: object bf1c4953c0ea4a045bf0975a916b53d247e7ca94 inconsistent object length (6093 vs 415232)
error: failed to run repack

# Check reflogs...
$ git reflog

# ...then clean
$ git reflog expire --expire=0 --all

# Now garbage collect again
$ git gc       
Counting objects: 3992, done.
Delta compression using 2 threads.
Compressing objects: 100% (3970/3970), done.
Writing objects: 100% (3992/3992), done.
Total 3992 (delta 2060), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.
# Done!

4
এটি যুক্ত করা হচ্ছে: যদি ব্যাকআপটিতে কোনও প্যাকটিতে ফাইলগুলি অনুপস্থিত থাকে তবে প্যাকটি থেকে একটি অঙ্কুর বের হওয়ার সঠিক উপায়টি হ'ল গিট বিড়াল-ফাইল ব্লাব << SH1>> file.dat ', এবং এটিকে ক্ষতিগ্রস্থ অবস্থায় ফিরিয়ে আনতে রেপো, ড্যানিয়েলের উত্তরে যেমন 'গিট হ্যাশ-অবজেক্ট-ডাব্লু.ড্যাট' করুন।
এমিল স্টায়ার্ক

আপনি সর্বশেষ দুর্নীতিগ্রস্থ প্যাকটি কীভাবে খুঁজে পাবেন? ধন্যবাদ
রোমেন আওয়ারগুরি

18

প্রথমে নীচের কমান্ডগুলি ব্যবহার করে দেখুন (প্রয়োজনে পুনরায় চালনা করুন):

$ git fsck --full
$ git gc
$ git gc --prune=today
$ git fetch --all
$ git pull --rebase

এবং তারপরেও আপনার এখনও সমস্যা রয়েছে, চেষ্টা করুন:

  • সমস্ত দূষিত বস্তু মুছে ফেলুন, যেমন

    fatal: loose object 91c5...51e5 (stored in .git/objects/06/91c5...51e5) is corrupt
    $ rm -v .git/objects/06/91c5...51e5
    
  • সমস্ত খালি বস্তু মুছে ফেলুন, যেমন

    error: object file .git/objects/06/91c5...51e5 is empty
    $ find .git/objects/ -size 0 -exec rm -vf "{}" \;
    
  • একটি "ভাঙা লিঙ্ক" বার্তাটি পরীক্ষা করে দেখুন:

    git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
    

    এটি আপনাকে বলবে যে দুর্নীতিগ্রস্থ ব্লবটি কোন ফাইল থেকে এসেছে!

  • ফাইলটি পুনরুদ্ধার করতে, আপনি সত্যিই ভাগ্যবান হতে পারেন, এবং এটি এমন সংস্করণ হতে পারে যা আপনি ইতিমধ্যে আপনার কার্যক্ষম গাছটিতে যাচাই করেছেন:

    git hash-object -w my-magic-file
    

    আবার, এবং যদি এটি হারিয়ে যাওয়া SHA1 (4b945 ..) কে আউটপুট করে দেয় আপনি এখন সব শেষ করেছেন!

  • ধরে নিই যে এটি কিছু পুরানো সংস্করণটি ভেঙে গেছে, এটি করার সহজতম উপায় হ'ল:

    git log --raw --all --full-history -- subdirectory/my-magic-file
    

    এবং এটি আপনাকে সেই ফাইলটির পুরো লগটি দেখিয়ে দেবে (দয়া করে বুঝতে পারেন যে আপনার যে গাছটি ছিল এটি উচ্চ স্তরের গাছ নাও হতে পারে, তাই এটি নিজেই কোন উপ-ডিরেক্টরিতে রয়েছে তা নির্ধারণ করার দরকার আছে), তবে আপনি এখন পুনরায় তৈরি করতে পারবেন হ্যাশ-অবজেক্টের সাথে আবার অজানা অবজেক্ট।

  • নিখোঁজ কমিট, গাছ বা ব্লব সহ সমস্ত রেফার তালিকা পেতে:

    $ git for-each-ref --format='%(refname)' | while read ref; do git rev-list --objects $ref >/dev/null || echo "in $ref"; done
    

    নিয়মিত ব্রাঞ্চ-ডি বা ট্যাগ-ডি কমান্ড ব্যবহার করে সেই কয়েকটি রেফ অপসারণ করা সম্ভব হবে না, কারণ যদি গিট দুর্নীতির বিষয়টি লক্ষ্য করে তবে তারা মারা যাবে। সুতরাং পরিবর্তে নদীর গভীরতানির্ণয় কমান্ড গিট আপডেট-রেফ-ডি-রেফ ব্যবহার করুন। মনে রাখবেন যে স্থানীয় শাখাগুলির ক্ষেত্রে, এই কমান্ডটি বাসী শাখা কনফিগারেশনটি .git / কনফিগারেশনে রেখে দিতে পারে। এটি ম্যানুয়ালি মুছে ফেলা যায় ([শাখা "রেফ" "বিভাগ দেখুন)।

  • সমস্ত রেফ পরিষ্কার হওয়ার পরে, রিফলগে এখনও ভাঙ্গা কমিট থাকতে পারে। আপনি গিট রিফ্লগের মেয়াদ - এক্সপায়ার = এখন - সমস্ত ব্যবহার করে সমস্ত রিফ্লোগগুলি সাফ করতে পারেন। আপনি যদি আপনার সমস্ত রিপ্লাগগুলি হারাতে না চান, আপনি ভাঙা রিফ্লোগগুলির জন্য পৃথক রেফগুলি অনুসন্ধান করতে পারেন:

    $ (echo HEAD; git for-each-ref --format='%(refname)') | while read ref; do git rev-list -g --objects $ref >/dev/null || echo "in $ref"; done
    

    (রেভ-লিস্টে গিট করার জন্য অ্যাড করা -g বিকল্পটি নোট করুন)) তারপরে, গিট রিফ্লগের মেয়াদ শেষ হয়ে যাওয়া --expire = এখন $ প্রতিটির উপর রেফ ব্যবহার করুন। সমস্ত ভাঙ্গা রেফ এবং রেফ্লোগগুলি শেষ হয়ে গেলে, সংগ্রহস্থলটি পরিষ্কার কিনা তা পরীক্ষা করতে গিট fsck - সম্পূর্ণ চালান। জঞ্জাল বস্তু ঠিক আছে।


নীচে আপনি কমান্ডগুলির উন্নত ব্যবহার সন্ধান করতে পারেন যা আপনার গিট রিপোজিটরিতে আপনার ডেটা হারিয়ে যাওয়ার কারণ হতে পারে যদি বুদ্ধিমানের সাথে ব্যবহার না করা হয়, সুতরাং আপনি দুর্ঘটনাক্রমে আপনার গিটের আরও ক্ষতি করার আগে একটি ব্যাকআপ তৈরি করুন। আপনি কী করছেন তা যদি আপনার নিজের ঝুঁকির চেষ্টা করে দেখুন।


আনার পরে উজানের শাখার শীর্ষে বর্তমান শাখাটি টানতে:

$ git pull --rebase

আপনি নতুন শাখাটি চেকআউট করে পুরানোটি মুছতে চেষ্টা করতে পারেন:

$ git checkout -b new_master origin/master

গিটে অপসারণের জন্য দূষিত বস্তুটি খুঁজে পেতে, নিম্নলিখিত আদেশটি চেষ্টা করুন:

while [ true ]; do f=`git fsck --full 2>&1|awk '{print $3}'|sed -r 's/(^..)(.*)/objects\/\1\/\2/'`; if [ ! -f "$f" ]; then break; fi; echo delete $f; rm -f "$f"; done

ওএসএক্সের sed -Eপরিবর্তে ব্যবহার করুন sed -r


অন্য ধারণা হ'ল প্যাকেট ফাইল থেকে সমস্ত বস্তুগুলি .git / অবজেক্টের অভ্যন্তরে পুনরায় জন্মানোর জন্য আনপ্যাক করা হয়, তাই আপনার সংগ্রহস্থলের মধ্যে নিম্নলিখিত কমান্ডগুলি চালনার চেষ্টা করুন:

$ cp -fr .git/objects/pack .git/objects/pack.bak
$ for i in .git/objects/pack.bak/*.pack; do git unpack-objects -r < $i; done
$ rm -frv .git/objects/pack.bak

উপরেরটি যদি সহায়তা না করে তবে আপনি অন্য রেপো থেকে গিটার অবজেক্টগুলি আরএসসিএন করতে বা অনুলিপি করার চেষ্টা করতে পারেন, যেমন

$ rsync -varu git_server:/path/to/git/.git local_git_repo/
$ rsync -varu /local/path/to/other-working/git/.git local_git_repo/
$ cp -frv ../other_repo/.git/objects .git/objects

নীচে চেকআউট করার চেষ্টা করার সময় ভাঙা শাখাটি ঠিক করতে:

$ git checkout -f master
fatal: unable to read tree 5ace24d474a9535ddd5e6a6c6a1ef480aecf2625

এটি সরানোর চেষ্টা করুন এবং আবার উজান থেকে চেকআউট করুন:

$ git branch -D master
$ git checkout -b master github/master

যদি গিট আপনাকে বিচ্ছিন্ন অবস্থায় masterনিয়ে যায় তবে চেকআউট করুন এবং এতে বিচ্ছিন্ন শাখায় মার্জ করুন।


আরেকটি ধারণা হ'ল বিদ্যমান মাস্টারকে পুনরাবৃত্তিভাবে পুনঃনির্মাণ করা:

$ git reset HEAD --hard
$ git rebase -s recursive -X theirs origin/master

আরো দেখুন:


2

দুর্নীতিগ্রস্থ ব্লব অবজেক্ট থেকে পুনরুদ্ধার করতে আমি অনুসরণ করা পদক্ষেপগুলি এখানে।

1) দুর্নীতিবাজ ব্লব সনাক্ত করুন

git fsck --full
  error: inflate: data stream error (incorrect data check)
  error: sha1 mismatch 241091723c324aed77b2d35f97a05e856b319efd
  error: 241091723c324aed77b2d35f97a05e856b319efd: object corrupt or missing
  ...

দুর্নীতি ব্লব 241091723c324aed77b2d35f97a05e856b319efd

2) দুর্নীতিগ্রস্থ ব্লবকে নিরাপদ স্থানে সরান (কেবলমাত্র ক্ষেত্রে)

mv .git/objects/24/1091723c324aed77b2d35f97a05e856b319efd ../24/

3) দুর্নীতিবাজ ব্লব এর পিতামাতার পান

git fsck --full
  Checking object directories: 100% (256/256), done.
  Checking objects: 100% (70321/70321), done.
  broken link from    tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
              to    blob 241091723c324aed77b2d35f97a05e856b319efd

মূল হ্যাশ 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180

4) ফাইলের নাম দুর্নীতিবাজ ব্লব সম্পর্কিত Get

git ls-tree 0716831e1a6c8d3e6b2b541d21c4748cc0ce7180
  ...
  100644 blob 241091723c324aed77b2d35f97a05e856b319efd    dump.tar.gz
  ...

ব্যাকআপে বা আপস্ট্রিম গিট সংগ্রহস্থলগুলিতে এই নির্দিষ্ট ফাইলটি সন্ধান করুন (আমার ক্ষেত্রে এটি ডাম্প.টার . gz )। তারপরে এটিকে আপনার স্থানীয় ভাণ্ডারের ভিতরে কোনও জায়গায় অনুলিপি করুন।

5) গিট অবজেক্ট ডাটাবেসে পূর্ববর্তী কলুষিত ফাইল যুক্ত করুন

git hash-object -w dump.tar.gz

6) উদযাপন!

git gc
  Counting objects: 75197, done.
  Compressing objects: 100% (21805/21805), done.
  Writing objects: 100% (75197/75197), done.
  Total 75197 (delta 52999), reused 69857 (delta 49296)

এটি আমার পক্ষে কাজ করে না। চতুর্থ ধাপের ফলস্বরূপ git ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: Could not read 19505205fd1f219993da9b75846fff3cf432152d, এবং আমি এটি আবারও দ্বিতীয় ধাপ 2 ছাড়াই চেষ্টা করেছি এবং এর ফলস্বরূপgit ls-tree 9504a07fb803edfdf0c1dd99c5d561274af87982 error: inflate: data stream error (invalid stored block lengths) fatal: failed to read object 19505205fd1f219993da9b75846fff3cf432152d: Invalid argument
রায়ান

1

গিট চেকআউট প্রকৃতপক্ষে পুনর্বিবেচনা থেকে পৃথক ফাইলগুলি চয়ন করতে পারে। কেবল এটি প্রতিশ্রুতিবদ্ধ হ্যাশ এবং ফাইলের নাম দিন। আরও বিস্তারিত তথ্য এখানে।

আমি অনুমান করি এটি নিরাপদে সমাধানের সবচেয়ে সহজ উপায়টি হল সর্বশেষতম নিঃশব্দ ব্যাকআপে ফিরে যাওয়া এবং তারপরে নির্বাচিতভাবে নতুন কমিটগুলি থেকে নিরবচ্ছিন্ন ফাইলগুলি বেছে নেওয়া। শুভকামনা!


1

এখানে দুটি ফাংশন রয়েছে যা আপনার ব্যাকআপ দূষিত হলে বা আপনার কয়েকটি আংশিক দূষিত ব্যাকআপ রয়েছে (যদি আপনি দূষিত বস্তুগুলি ব্যাকআপ করেন তবে এটি ঘটতে পারে) সাহায্য করতে পারে।

আপনি পুনরুদ্ধার করার চেষ্টা করছেন রেপোতে উভয়ই চালান।

স্ট্যান্ডার্ড সতর্কতা: কেবলমাত্র যদি আপনি সত্যিই মরিয়া হয়ে থাকেন এবং আপনি আপনার (দূষিত) রেপো ব্যাক আপ করে থাকেন তবেই ব্যবহার করুন। এটি কোনও সমস্যার সমাধান করতে পারে না, তবে কমপক্ষে দুর্নীতির স্তরটি হাইলাইট করা উচিত।

fsck_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git fsck --full --no-dangling 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

pushd "$1" >/dev/null
fsck_rm_corrupted
popd >/dev/null

এবং

unpack_rm_corrupted() {
    corrupted='a'
    while [ "$corrupted" ]; do
        corrupted=$(                                  \
        git unpack-objects -r < "$1" 2>&1 >/dev/null \
            | grep 'stored in'                          \
            | sed -r 's:.*(\.git/.*)\).*:\1:'           \
        )
        echo "$corrupted"
        rm -f "$corrupted"
    done
}

if [ -z "$1" ]  || [ ! -d "$1" ]; then
    echo "'$1' is not a directory. Please provide the directory of the git repo"
    exit 1
fi

for p in $1/objects/pack/pack-*.pack; do
    echo "$p"
    unpack_rm_corrupted "$p"
done

0

গিট অ্যাড-এ এবং গিট কমিটের মতো কিছু পরিবর্তন যুক্ত করতে আমি এই সমস্যার সমাধান করেছি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.