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 ব্যবহার করব? একটা দ্রুত সিদ্ধান্ত-গাইড
- পুশ হয়নি, ফিক্স করে re-commit করতে চান →
git reset --soft HEAD~1 - পুশ হয়নি, আংশিক re-stage করতে চান →
git reset HEAD~1(mixed) - পরিবর্তন পুরোপুরি যাবেই →
git reset --hard HEAD~1(আফসোস করলে reflog জানে) - শেয়ারড ব্রাঞ্চে ইতিমধ্যে পুশ হয়ে গেছে →
git revert HEAD - 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 ↗
পরের হাউ-টু ইমেইলে পান
প্রতি পোস্টে একটি ইমেইল। সমাধান করুন, এগিয়ে যান।
এটা কী?journalctl Cheat Sheet: লগ টেইল, ফিল্টার ও ফলো
লেখাগুলো ভালো লাগছে? এমন জিনিস বানানোই আমার পেশা। আমাকে নিন