হ্যাঁ — প্রায় সবসময়ই উদ্ধার সম্ভব। অস্ত্রের নাম: git reflog

আগের আলোচনাগুলোতে বারবার এক লাইনে প্রতিশ্রুতি দিয়ে রেখেছি — "reflog তো আছেই।" এবার পুরো গল্পটা।

প্রথমে শান্ত হোন: commit আসলে "হারায়নি"

প্রথম আলোচনার মানসিক মডেলে ফিরুন। git reset --hard HEAD~2 কী করেছে? শুধু branch pointer-টা পেছনে সরিয়েছে। Commit object-গুলো .git/objects-এ দিব্যি বসে আছে — শুধু তাদের দিকে তাক করা কোনো branch/tag আর নেই। এদের বলে unreachable (dangling) commit

আগে:   A---B---C---D   main
পরে:   A---B           main        C---D  (এতিম, কিন্তু জীবিত)

Git এতিম object সাথে সাথে মোছে না — garbage collection (git gc) মোছে, এবং সেটাও ডিফল্টে ~৩০–৯০ দিন পরে। অর্থাৎ আপনার হাতে অঢেল সময় — সমস্যা শুধু একটাই: C আর D-এর hash জানা নেই। এখানেই reflog।

git reflog কী

Git প্রতিবার আপনার HEAD যেখানে যেখানে গেছে তার একটা লোকাল ডায়েরি রাখে — প্রতিটা commit, checkout, merge, rebase, reset, cherry-pick — সব। এটাই reference log:

git reflog
b7e2a91 HEAD@{0}: reset: moving to HEAD~2      ← দুর্ঘটনার মুহূর্ত
f4c8d12 HEAD@{1}: commit: Add discount tests   ← এটাই হারানো D!
a9b3e56 HEAD@{2}: commit: Add discount service ← হারানো C
b7e2a91 HEAD@{3}: checkout: moving from feature-x to main
...

পড়ার নিয়ম: HEAD@{0} = এইমাত্র, নিচে যত নামবেন তত অতীত। দুর্ঘটনার ঠিক আগের লাইনটা খুঁজুন — ওখানেই আপনার হারানো সম্পদের hash।

উদ্ধার — তিনটা পথ

পথ ১: সব ফিরিয়ে আনা (সবচেয়ে সাধারণ)

git reset --hard f4c8d12      # বা: git reset --hard HEAD@{1}

হ্যাঁ — যে অস্ত্র ডুবিয়েছিল, সেই অস্ত্রই উদ্ধার করে। Reset তো শুধু pointer সরানো; এবার সঠিক দিকে সরালেন। main আবার D-তে, সব আগের মতো।

পথ ২: আগে দেখে নেওয়া (সতর্ক সংস্করণ)

নিশ্চিত না হলে সরাসরি reset না করে আগে পরিদর্শন:

git show f4c8d12              # commit-টা কী ছিল দেখুন
git checkout f4c8d12          # detached HEAD-এ ঘুরে দেখুন (প্রথম আলোচনার সেই state!)

পথ ৩: আলাদা branch-এ উদ্ধার

git branch rescue f4c8d12

এক লাইনে বিপদ শেষ — এখন rescue নামের pointer commit-গুলোকে ধরে রেখেছে, gc আর ছুঁতে পারবে না। তারপর ধীরেসুস্থে merge/cherry-pick করুন।

Branch-specific reflog-ও আছে:

git reflog show feature-x     # নির্দিষ্ট branch-এর pointer কোথায় কোথায় ছিল

Rebase-দুর্ঘটনা, ভুল branch delete — সব উদ্ধারেও একই কৌশল।

সততার জায়গা: কী উদ্ধার হয় না

Reset-আলোচনার সেই সতর্কবার্তা এখানে পূর্ণ অর্থ পায়। Reflog শুধু commit-হওয়া জিনিস ফেরাতে পারে, কারণ Git-এর snapshot শুধু commit-এই তৈরি হয়:

হারানো জিনিস উদ্ধারযোগ্য?
Commit-করা কাজ ✅ reflog দিয়ে
Staged (git add করা) কিন্তু commit-না-করা ⚠️ আংশিক — git fsck --lost-found দিয়ে blob-স্তরে খোঁজা যায়, কষ্টসাধ্য
শুধু working directory-তে থাকা এডিট ❌ চিরতরে — Git কখনো দেখেইনি

আর দুটো সীমাবদ্ধতা: reflog সম্পূর্ণ লোকাল — সহকর্মীর মেশিনের বা সার্ভারের reflog আপনার কাছে নেই, fresh clone-এ reflog শূন্য থেকে শুরু। আর এন্ট্রিগুলোর মেয়াদ ডিফল্টে ৯০ দিন (unreachable-দের জন্য ৩০)।

এখান থেকেই ব্যবহারিক শিক্ষাটা: ঘন ঘন commit করুন। "নোংরা" WIP commit-ই আপনার সেফটি নেট — আর সেগুলো পরে গুছানোর জন্য rebase -i তো শিখেই ফেলেছেন। Commit-করা কাজ Git-এ হারানো রীতিমতো কঠিন; commit-না-করা কাজের কোনো বীমা নেই।

এক লাইনে (interview-সংস্করণ)

"হ্যাঁ — reset --hard commit মোছে না, শুধু pointer সরায়; commit-গুলো unreachable হয়ে objects-এ থেকেই যায় (gc-র আগ পর্যন্ত, ~৩০–৯০ দিন), আর git reflog হলো HEAD-এর চলাচলের লোকাল ডায়েরি — সেখান থেকে হারানো commit-এর hash নিয়ে git reset --hard <hash> বা git branch rescue <hash> করলেই উদ্ধার; তবে সীমাটাও জানা জরুরি — reflog লোকাল ও মেয়াদি, এবং কখনো commit-ই-হয়নি এমন কাজ কোনো জাদুতেই ফেরে না।"

Share