ব্লগে ফিরুন

Git Undo Last Commit: পরিবর্তন রেখে নিরাপদ বাতিল

৩ সেপ্টেম্বর, ২০২৬

TL;DR: শেষ commit বাতিল করেও পরিবর্তন রাখতে git reset --soft HEAD~1 চালান (পরিবর্তন staged থাকে) বা git reset HEAD~1 (পরিবর্তন working tree-তে থাকে)। Commit আগেই পুশ হয়ে গেলে বদলে git revert HEAD চালান — এটি নতুন একটি commit বানায়, যা history না ঘুরিয়ে পুরোনোটার পরিবর্তন বাতিল করে। “অল্পেই commit করে ফেলেছি” — এমন প্রায় প্রতিটি মুহূর্ত এই তিনটা কমান্ডই ঢেকে ফেলে। বাকিটা প্রতিটি কেসের হাঁটাপথ, --soft, --mixed, --hard-এর পার্থক্য, আর কিছু ভুল হলে উদ্ধারের রাস্তা। Linux, macOS বা Windows-এর যেকোনো সাম্প্রতিক Git ইনস্টলে নিচের সব কমান্ড চলে।

শেষ commit বাতিল করে পরিবর্তন কীভাবে রাখব?

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

# Commit history-তে কোথাও থাকে না — পরিবর্তন ফিরে যায় staging area-তে
git reset --soft HEAD~1

# বদলে পরিবর্তন ফিরে যায় working tree-তে (unstaged)
git reset HEAD~1

HEAD~1 মানে “HEAD এখন যেখানে, তার ঠিক এক commit আগে”। যেকোনো একটি চালানোর পরেও ফাইলগুলো ডিস্কে অক্ষত — নড়েছে শুধু ব্রাঞ্চ পয়েন্টার। git status দিয়ে যাচাই করুন: --soft দিলে পরিবর্তন staged, ফিক্স জুড়ে নিয়ে re-commit করার জন্য তৈরি; ফ্ল্যাগ ছাড়া সেগুলো unstaged, তাই আগে নিশ্চিন্তে এডিট করতে পারেন।

শুধু শেষ commit-এ আরেকটা ফাইল যোগ করাই মাত্র চাইলে নিরাপদ অভ্যাস — বাতিলই করবেন না:

git add forgotten-file.txt
git commit --amend --no-edit

--amend শেষ commit-টাকে জায়গাতেই বদলে দেয় (এখানে commit message বদলানো হয়নি)। খেয়াল রাখুন, পুশ করা commit amend করা history ঘুরিয়ে দেয় — সে প্রসঙ্গে নিচে।

—soft, —mixed আর —hard-এর পার্থক্য কী?

মুখস্থ করার মতো অংশ এটাই, কারণ ফ্ল্যাগটাই ঠিক করে আপনার পরিবর্তন শেষ হবে কোথায় — আর হারানো যাবে কি না:

ফ্ল্যাগCommit বাতিল হয়?ডিস্কের পরিবর্তনStaged থাকে?সাধারণ ব্যবহার
--softহ্যাঁথাকেহ্যাঁছোট ফিক্সসহ re-commit
--mixed (ডিফল্ট)হ্যাঁথাকেনাপরিবর্তন নতুন করে গুছিয়ে আংশিক stage
--hardহ্যাঁমুছে যায়কাজ সম্পূর্ণ ফেলে দেওয়া
git revertনা (নতুন commit)থাকেআগেই পুশ হয়ে যাওয়া commit বাতিল

--hard-ই একমাত্র বিপজ্জনক: এটি commit এবং পরিবর্তন দুটোই ফেলে দেয়। যেকোনো reset --hard-এর আগে যা আছে তা stash করুন বা ব্রাঞ্চ করে রাখুন:

git branch backup-before-reset   # সস্তা বিমা
git reset --hard HEAD~1          # commit + পরিবর্তন দুটোই শেষ

বিপজ্জনক ভার্সনটা ইতিমধ্যে চালিয়ে ফেললেও সব শেষ নয় — git reflog HEAD কোথায় কোথায় গিয়েছিল, সেটাই মনে রাখে:

git reflog                       # হারানো commit-এর hash খুঁজুন
git reset --hard HEAD@{1}        # অথবা: git reset --hard <hash>

reflog ডিফল্টে dangling commit প্রায় 90 দিন ধরে রাখে, তাই “ভুলে hard-reset করে ফেলেছি” প্রায় সবসময়ই উদ্ধারযোগ্য — garbage collection-এর আগে নড়লে।

Commit আগেই পুশ করে ফেললে কী হবে?

Commit শেয়ারড ব্রাঞ্চে গিয়ে থাকলে (নিজের ফিচার ব্রাঞ্চ ছাড়া অন্য যেকোনো কিছু), history ঘুরাবেন নাgit revert ব্যবহার করুন — এটি বিপরীত পরিবর্তন হিসাব করে সেটাই commit করে:

git revert HEAD
git push

যাঁরা pull করবেন তাঁরা কেবল একটা নতুন commit পাবেন, যা পুরোনোটার পরিবর্তন সরিয়ে দেয়। কোনো force-push নেই, ভাঙা কলিগ নেই। টানা কয়েকটা commit বাতিল করতে হলে রেঞ্জ revert করুন: git revert --no-commit HEAD~3..HEAD && git commit

বিকল্পটা — git reset --hard HEAD~1 && git push --force-with-lease — কেবল এমন ব্রাঞ্চে মেনে নেওয়া যায় যার ওপর আর কেউ কাজ বানায় না, আর --force-with-lease (কখনোই খালি --force নয়)-ই নিরাপদ রূপ, কারণ ফাঁকে কেউ পুশ করে ফেললে সে অস্বীকার করে দেয়। শেয়ারড ব্রাঞ্চে force-push করাই সেই কারণ, যাতে টিম কমিট হারায় আর CI-এর লগ রহস্যজনকভাবে কারও চেকআউটের সাথে মেলে না।

শেষ commit বাতিল করে পরের জন্য জমিয়ে রাখব কীভাবে?

মাঝে মাঝে commit-টা ভালো কাজ, শুধু ঠিকানা ভুল — ভুল ব্রাঞ্চে, বা অসময়ে। বাতিল না করে সরিয়ে দিন:

git branch stash-commit          # commit-টা নতুন ব্রাঞ্চে রেখে দিন
git reset --hard HEAD~1          # তারপর বর্তমান ব্রাঞ্চ পরিষ্কার করুন

অথবা শুধু সেই commit-টাকে অন্য ব্রাঞ্চে নিন, বর্তমানটা স্পর্শ না করে:

git cherry-pick <hash>           # টার্গেট ব্রাঞ্চে অবস্থান করার সময়

reset --soft, cherry-pick আর revert-এর মাঝে এমন কোনো commit নেই যা সরানো বা বাতিল করা যায় না — কৌশল হলো ফ্ল্যাগ তুলে নেওয়ার আগে “সরাব” না “বাতিল করব” ঠিক করা।

কোন undo ব্যবহার করব? একটা দ্রুত সিদ্ধান্ত-গাইড

  1. পুশ হয়নি, ফিক্স করে re-commit করতে চানgit reset --soft HEAD~1
  2. পুশ হয়নি, আংশিক re-stage করতে চানgit reset HEAD~1 (mixed)
  3. পরিবর্তন পুরোপুরি যাবেইgit reset --hard HEAD~1 (আফসোস করলে reflog জানে)
  4. শেয়ারড ব্রাঞ্চে ইতিমধ্যে পুশ হয়ে গেছেgit revert HEAD
  5. Commit আসলে অন্য ব্রাঞ্চের হওয়া উচিত → undo নয়, cherry-pick

শেষ একটা অপারেশনাল টিপ: খারাপ একটা commit সার্ভারেও চলে গেলে — বানোয়াট deploy হুক, force-push-এর পরে দুর্ব্যবহারী CI রানার — পরের ঠিকানা Git নয়, মেশিনের লগ। যেকোনো systemd বক্সে journalctl -u <service> -n 100 ঠিক কী চলেছে কবে, সেটাই দেখায়; আমাদের journalctl cheat sheet-এ কপি-পেস্ট প্যাটার্নগুলো আছে। আর diff রিভিউতে লোকাল LLM টুলিং আপনার ওয়ার্কফ্লোতে থাকলে, দুই প্রধান অপশনের তুলনা আছে Ollama vs LM Studio-তে।

— mrsaynothing

— mrsaynothing

AI, Linux ও self-hosting নিয়ে ফিল্ড নোটস।

পোস্টটি নিয়ে dev.to-তে আলোচনা করুন dev.to ↗

পরের হাউ-টু ইমেইলে পান

প্রতি পোস্টে একটি ইমেইল। সমাধান করুন, এগিয়ে যান।

self-hosted · কোনো তৃতীয় পক্ষ নেই · এক ক্লিকে আনসাবস্ক্রাইব

এটা কী?

journalctl Cheat Sheet: লগ টেইল, ফিল্টার ও ফলো

লেখাগুলো ভালো লাগছে? এমন জিনিস বানানোই আমার পেশা। আমাকে নিন