অধ্যায় 2 · Git ও GitHub
ভুল শোধরানো: restore, reset ও revert
- পৃষ্ঠা 7 / 22
- 15 মিনিট পড়া
Git নিয়ে সবাই ভুল করে: কোনো এক্সপেরিমেন্ট মডেলের আউটপুট নষ্ট করে দেয়, একটা স্ক্র্যাচ নোটবুক ভুল করে স্টেজ হয়ে যায়, কমিট মেসেজে বানান ভুল থাকে, এমন একটা কমিট হয়ে যায় যেটা কখনো হওয়ার কথা ছিল না, কিংবা টিমের কাছে চলে যাওয়া একটা পরিবর্তন ভুল প্রমাণিত হয়। সুখবর হলো, Git কমিট করা কাজ প্রায় কখনোই হারায় না, আর প্রায় প্রতিটা ভুলের একটা পরিষ্কার, নির্দিষ্ট আনডু আছে। দুঃসংবাদ হলো, আনডু কমান্ডগুলো দেখতে একরকম, আর কয়েকটা সত্যিই কাজ মুছে দেয়।
এই পাতায় আপনি একটা মানসিক মডেল পাবেন (ভুলটা Git-এর তিনটা এলাকার কোনটায়, নাকি শেয়ার করা হিস্ট্রিতে?) এবং প্রতিটা ক্ষেত্রের সঠিক কমান্ড: git restore, git commit --amend, git reset আর git revert।
যা শিখবেন
git restoreআরgit restore --stagedদিয়ে ওয়ার্কিং ট্রির এডিট ফেলে দেওয়া এবং ফাইল আনস্টেজ করা।git commit --amendদিয়ে শেষ কমিটের মেসেজ বা কনটেন্ট ঠিক করা।git reset --soft,--mixedআর--hardপ্রত্যেকটা কী করে, এবং কখন--hardবিপজ্জনক।- একটা কমিট শেয়ার করে ফেলার পর কেন
git revert-ই সঠিক আনডু। - একটা সিদ্ধান্ত-টেবিল: "আমি কী আনডু করতে চাই?" → কমান্ড।
উদাহরণ প্রজেক্ট সাজানো
আবার একটা নতুন রিভিউ অ্যানালাইজার, তবে এবার শব্দের তালিকা আলাদা ছোট ফাইল words.py-তে, আর দুটো কমিটের হিস্ট্রিসহ:
mkdir -p ~/projects/review-analyser
cd ~/projects/review-analyser
git init -q
cat > words.py <<'EOF'
POSITIVE = {"good", "great", "fast", "love"}
NEGATIVE = {"bad", "slow", "broken", "late"}
EOF
cat > analyse.py <<'EOF'
"""Label product reviews as positive, negative or neutral."""
import csv
from words import NEGATIVE, POSITIVE
def label(text):
words = text.lower().split()
score = sum(w in POSITIVE for w in words) - sum(w in NEGATIVE for w in words)
return "positive" if score > 0 else "negative" if score < 0 else "neutral"
if __name__ == "__main__":
with open("reviews.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
print(label(row["text"]), "|", row["text"])
EOF
cat > reviews.csv <<'EOF'
id,text
1,great phone and fast delivery
2,battery is bad and the box was broken
3,it works
EOF
git add .
git commit -q -m "Add keyword review analyser"
echo "# Review analyser" > README.md
git add README.md
git commit -q -m "Add README"
git log --oneline
python analyse.py5794c66 Add README
7f5e38e Add keyword review analyser
positive | great phone and fast delivery
negative | battery is bad and the box was broken
neutral | it worksপ্রথমে প্রশ্ন: ভুলটা কোথায়?
প্রতিটা আনডু নির্ভর করে অবাঞ্ছিত পরিবর্তনটা এখন কোথায় আছে তার ওপর। ভার্সন কন্ট্রোল ও আপনার প্রথম রিপোজিটরি পাতার তিনটা এলাকার কথা মনে করুন, সঙ্গে চতুর্থ একটা, যেটা পরের পাতাগুলোতে পাবেন: GitHub-এ থাকা কপি, যা অন্যদের কাছেও আছে।
working tree staging area local commits shared history
(your files) (the index) (your branch) (pushed to GitHub)
| | | |
git restore FILE git restore --staged git commit --amend git revert COMMIT
(discard edits) FILE (unstage) git reset [--soft|--mixed| (new commit that
--hard] COMMIT undoes an old one)যত ডানে যাবেন, তত সাবধান হতে হবে। কমিট না করা ওয়ার্কিং ট্রির পরিবর্তন একবার ফেলে দিলে Git সেটা আর ফেরাতে পারে না। শুধু আপনার মেশিনে থাকা কমিট যত খুশি নতুন করে লেখা যায়। অন্যদের কাছে চলে যাওয়া কমিট নতুন করে লেখা চলবে না; বরং এমন একটা নতুন কমিট যোগ করবেন, যা সেটাকে আনডু করে।
ওয়ার্কিং ট্রির এডিট ফেলা: git restore
নাদিয়া একটা এক্সপেরিমেন্ট করছে: কী হয় দেখতে সে নেগেটিভ শব্দের তালিকা খালি করে দিল, আর এখন অ্যানালাইজার ভাঙা বাক্সের রিভিউকে "neutral" বলছে:
cat > words.py <<'EOF'
POSITIVE = {"good", "great", "fast", "love"}
NEGATIVE = set()
EOF
git diff
python analyse.pydiff --git a/words.py b/words.py
index 32edebb..02d5629 100644
--- a/words.py
+++ b/words.py
@@ -1,2 +1,2 @@
POSITIVE = {"good", "great", "fast", "love"}
-NEGATIVE = {"bad", "slow", "broken", "late"}
+NEGATIVE = set()
positive | great phone and fast delivery
neutral | battery is bad and the box was broken
neutral | it worksএক্সপেরিমেন্ট ব্যর্থ হয়েছে, আর সে ফাইলটা ঠিক শেষ কমিটের মতো চায়। git restore কমিট করা সংস্করণটা ওয়ার্কিং ট্রির ওপর কপি করে ফেরত দেয়:
git restore words.py
git status --short
python analyse.pypositive | great phone and fast delivery
negative | battery is bad and the box was broken
neutral | it worksgit status --short কিছু না দেখানোর মানে ওয়ার্কিং ট্রি পরিষ্কার, আর ২ নম্বর রিভিউ আবার negative। git restore . বর্তমান ফোল্ডারের সব বদলানো ফাইলের জন্য একই কাজ করে।
সাবধান: এটা Git-এর সেই কয়েকটা কমান্ডের একটা, যা সত্যিই কাজ নষ্ট করে। যে এডিটগুলো ফেলে দিচ্ছেন সেগুলো কখনো কমিট হয়নি, তাই কোথাও কোনো কপি নেই, আর কোনো Git কমান্ড সেগুলো ফেরাতে পারবে না। পরে লাগতে পারে মনে হলে বরং একটা ব্রাঞ্চে কমিট করুন (পরের পাতায়) অথবা
git stashব্যবহার করুন (অ্যাডভান্সড টিউটোরিয়ালে)।
ফাইল আনস্টেজ করা: git restore --staged
এবার একটা আসল উন্নতি: "terrible" নেগেটিভ তালিকায় থাকা উচিত। কাজের ফাঁকে নাদিয়া একটা স্ক্র্যাচ নোটবুকও বানিয়েছিল, আর তাড়াহুড়োয় git add . দুটোকেই স্টেজ করে ফেলেছে:
cat > words.py <<'EOF'
POSITIVE = {"good", "great", "fast", "love"}
NEGATIVE = {"bad", "slow", "broken", "late", "terrible"}
EOF
echo '{"cells": []}' > scratch.ipynb
git add .
git statusOn branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: scratch.ipynb
modified: words.pyআনডুটা Git নিজেই হিন্টে দেখিয়ে দেয়: git restore --staged <file>। এটা ফাইলটাকে স্টেজিং এরিয়া থেকে বের করে আনে, আর ডিস্কে আপনার কপিতে হাত দেয় না:
git restore --staged scratch.ipynb
git status --shortM words.py
?? scratch.ipynbপ্রথম কলাম স্টেজিং এরিয়া, দ্বিতীয় কলাম ওয়ার্কিং ট্রি: M মানে words.py বদলানো এবং স্টেজ করা, আর ?? মানে scratch.ipynb আবার আনট্র্যাকড। নোটবুকটা আছেই; শুধু কমিটে যাচ্ছে না। আসল পরিবর্তনটা কমিট করুন:
git commit -q -m "Add terrible to negative words"
git log --onelinee2fbfcf Add terrible to negative words
5794c66 Add README
7f5e38e Add keyword review analysergit restore --source দিয়ে যেকোনো পুরোনো কমিট থেকেও ফাইল আনতে পারে। যেমন git restore --source=HEAD~1 words.py এক কমিট আগের শব্দতালিকা আপনার ওয়ার্কিং ট্রিতে বসিয়ে দেয় (HEAD হলো আপনি যে কমিটে আছেন, HEAD~1 তার প্যারেন্ট, HEAD~2 তার আগেরটা)। আপনি কমিট না করা পর্যন্ত কিছুই কমিট হয় না, আর git restore words.py আপনাকে আগের অবস্থায় ফিরিয়ে আনে।
শেষ কমিট ঠিক করা: git commit --amend
ভুল মেসেজ
নাদিয়া ব্যাচ প্রসেসিং যোগ করল আর মেসেজে বানান ভুল করল:
cat >> analyse.py <<'EOF'
def label_all(texts):
return [label(t) for t in texts]
EOF
git commit -q -am "Add bach labeling"
git log --oneline -1ea145ce Add bach labelinggit commit --amend শেষ কমিটকে একটা নতুন কমিট দিয়ে বদলে দেয়। -m দিলে নতুন মেসেজ বসে:
git commit --amend -q -m "Add batch labelling with label_all()"
git log --oneline -1e73f7ad Add batch labelling with label_all()হ্যাশটা খেয়াল করুন: বদলে গেছে। অ্যামেন্ড করা কমিট আসলে একটা নতুন কমিট (মেসেজ আলাদা, তাই স্ন্যাপশটের ডেটা আলাদা, তাই হ্যাশও আলাদা); পুরোনোটা শুধু ব্রাঞ্চে আর নেই।
ভুলে যাওয়া ফাইল
তারপর নাদিয়া খেয়াল করল, নতুন ফাংশনের জন্য স্যাম্পল ডেটায় একটা টেস্ট রিভিউ থাকা উচিত ছিল, যা একই কমিটের অংশ হওয়ার কথা। ফাইলটা স্টেজ করে --no-edit দিয়ে অ্যামেন্ড করুন, মেসেজ আগের মতোই থাকবে:
echo "4,terrible support and late refund" >> reviews.csv
git add reviews.csv
git commit --amend -q --no-edit
git show --stat --oneline HEAD60458d3 Add batch labelling with label_all()
analyse.py | 4 ++++
reviews.csv | 1 +
2 files changed, 5 insertions(+)একটাই কমিট, দুটো ফাইলসহ, যেন প্রথমবারেই সে ঠিকঠাক করেছিল।
নিয়ম: শুধু সেই কমিটই অ্যামেন্ড করুন, যা আপনি এখনো পুশ করেননি। কমিট একবার GitHub-এ গেলে সহকর্মীদের কাছে সেটা থাকতে পারে, আর নতুন হ্যাশ দিয়ে সেটা বদলালে আপনার আর তাদের হিস্ট্রি মেলে না। শেয়ার করা কমিটের জন্য
git revertব্যবহার করুন (নিচে)।
ব্রাঞ্চ পিছিয়ে নেওয়া: git reset
git reset COMMIT বর্তমান ব্রাঞ্চকে একটা পুরোনো কমিটে নিয়ে যায়, ফলে নতুন কমিটগুলো আর ব্রাঞ্চে থাকে না। তিনটা মোডের পার্থক্য শুধু এটুকু: ওই কমিটগুলোর পরিবর্তনের কী হবে।
| কমান্ড | ব্রাঞ্চ পিছোয়? | স্টেজিং এরিয়া | ওয়ার্কিং ট্রি (আপনার ফাইল) | কখন ব্যবহার করবেন |
|---|---|---|---|---|
git reset --soft HEAD~1 | হ্যাঁ | পরিবর্তন থাকে, স্টেজ অবস্থায় | অপরিবর্তিত | কমিট নতুন করে করতে: মেসেজ বদলাতে বা অন্যভাবে ভাগ করতে |
git reset HEAD~1 (--mixed, ডিফল্ট) | হ্যাঁ | খালি হয়ে যায় | অপরিবর্তিত: পরিবর্তনগুলো আনস্টেজড এডিট হিসেবে ফিরে আসে | কমিট আনডু করে কাজ রেখে দিতে, যাতে নতুন করে বেছে কমিট করা যায় |
git reset --hard HEAD~1 | হ্যাঁ | খালি হয়ে যায় | কমিটের সাথে মিলিয়ে ওভাররাইট হয় | কমিটগুলো এবং কমিট না করা সব এডিট ফেলে দিতে |
চলুন একটা ফেলনা কমিটে তিনটাই চেষ্টা করি। নাদিয়া একটা THRESHOLD সেটিং যোগ করল, যেটা নিয়ে সে এখনো নিশ্চিত নয়, এবং কমিটও করে ফেলল:
echo "THRESHOLD = -1" >> words.py
git commit -q -am "Try a lower threshold"
git log --oneline -2b624bab Try a lower threshold
60458d3 Add batch labelling with label_all()--soft: কমিট আনডু, সবকিছু স্টেজড থাকে
git reset --soft HEAD~1
git log --oneline -1
git status --short60458d3 Add batch labelling with label_all()
M words.py
?? scratch.ipynbকমিটটা ব্রাঞ্চ থেকে চলে গেছে, আর তার পরিবর্তন স্টেজড (প্রথম কলামে M), আবার কমিট করার জন্য প্রস্তুত, হয়তো আরও ভালো মেসেজ দিয়ে।
--mixed (ডিফল্ট): কমিট আনডু, এডিট আনস্টেজড থাকে
git commit -q -m "Try a lower threshold"
git reset HEAD~1
git status --shortUnstaged changes after reset:
M words.py
M words.py
?? scratch.ipynbGit যে ফাইলগুলো আনস্টেজ করল সেগুলোর কথা জানায়। এডিটটা এখনো words.py-তে আছে, তবে এখন দ্বিতীয় কলামে (বদলানো, স্টেজড নয়)। একবারে বেশি কমিট করে ফেললে এবং ছোট ছোট অংশে নতুন করে স্টেজ করতে চাইলে এই মোড ব্যবহার করুন। (কমিট ছাড়া শুধু git reset মানে git reset HEAD: সবকিছু আনস্টেজ, যা git restore --staged . বলার পুরোনো উপায়।)
--hard: কমিট আনডু এবং পরিবর্তন ফেলে দেওয়া
git commit -q -am "Try a lower threshold"
git reset --hard HEAD~1
git status --short
cat words.pyHEAD is now at 60458d3 Add batch labelling with label_all()
?? scratch.ipynb
POSITIVE = {"good", "great", "fast", "love"}
NEGATIVE = {"bad", "slow", "broken", "late", "terrible"}কমিটটা নেই, আর words.py-তে THRESHOLD লাইনটাও নেই। --hard ট্র্যাক করা ফাইলের কমিট না করা প্রতিটা পরিবর্তনও মুছে দেয়, শুধু ওই কমিটের নয়; তাই এটা ব্যবহারের আগে git status চালান।
সেফটি নেট: git reflog
কমিটটা কি চিরতরে হারিয়ে গেল? না। HEAD যেসব জায়গায় ছিল, Git সব reflog-এ লিখে রাখে, ডিফল্টে প্রায় ৯০ দিন, শুধু আপনার মেশিনে:
git reflog -360458d3 HEAD@{0}: reset: moving to HEAD~1
b624bab HEAD@{1}: commit: Try a lower threshold
60458d3 HEAD@{2}: reset: moving to HEAD~1HEAD@{1} মানে "এক মুভ আগে HEAD যেখানে ছিল": সেই থ্রেশহোল্ড কমিট। git reset --hard HEAD@{1} (অথবা তার হ্যাশ) সেটাকে সোজা ফিরিয়ে আনত। অ্যাডভান্সড টিউটোরিয়ালে reflog দিয়ে হারানো কাজ উদ্ধারের বিস্তারিত আছে। তবে সীমাটা মনে রাখুন: reflog শুধু কমিট চেনে। git restore বা git reset --hard যে কমিট-না-করা এডিট নষ্ট করে, সেগুলো এতে নেই।
শেয়ার করা কমিট আনডু: git revert
reset আর --amend হিস্ট্রি নতুন করে লেখে: কমিট ব্রাঞ্চ থেকে অদৃশ্য হয়। কমিটটা শুধু আপনার কাছে থাকলে সেটা ঠিক আছে। কিন্তু কমিট একবার পুশ হয়ে অন্যরা পুল করে ফেললে সেটা নতুন করে লিখলে ঝামেলা হয়: তাদের হিস্ট্রিতে ওটা থেকেই যায়, আপনার পরের পুশ প্রত্যাখ্যাত হয়, আর জোর করে পুশ করলে তাদের কাজ নষ্ট হতে পারে।
শেয়ার করা হিস্ট্রির জন্য git revert ব্যবহার করুন। এটা খারাপ কমিটকে যেখানে আছে সেখানেই রাখে, আর এমন একটা নতুন কমিট যোগ করে যা ঠিক উল্টো পরিবর্তন প্রয়োগ করে। ধরুন এই পরিবর্তনটা পুশ হয়ে গেছে, আর পরদিন দেখা গেল কাস্টমার রিভিউতে "fine" প্রায়ই অভিযোগের সাথে আসে ("fine, but late"), তাই এটাকে positive ধরা ভুল ছিল:
cat > words.py <<'EOF'
POSITIVE = {"good", "great", "fast", "love", "fine"}
NEGATIVE = {"bad", "slow", "broken", "late", "terrible"}
EOF
git commit -q -am "Count fine as positive"
git revert --no-edit HEADGit যেকোনো কমিটের মতোই নতুন কমিটের একটা ছোট সারসংক্ষেপ ছাপে। এবার লগ দেখুন:
git log --oneline -413c3fa4 Revert "Count fine as positive"
6f4269c Count fine as positive
60458d3 Add batch labelling with label_all()
e2fbfcf Add terrible to negative wordsহিস্ট্রি এখন সত্যিকারের গল্পটা বলছে: পরিবর্তনটা করা হয়েছিল, তারপর ইচ্ছা করে আনডু করা হয়েছে। সহকর্মীরা সাধারণ পুলেই রিভার্ট পেয়ে যায়, কারো হিস্ট্রি নতুন করে লেখা হয় না। --no-edit না দিলে Git আপনার এডিটর খুলে Revert "Count fine as positive" মেসেজ দেখায়, যাতে আপনি কেন সেটা লিখতে পারেন (ভালো অভ্যাস)। শেষটাই নয়, যেকোনো কমিট হ্যাশ দিয়ে রিভার্ট করা যায়, আর Git উল্টো পরিবর্তনটা বের করে নেয়; পরের কমিটগুলো একই লাইন ছুঁয়ে থাকলে আপনাকে কনফ্লিক্ট মেটাতে হবে, যেমন পরের পাতায় দেখবেন।
git diff HEAD~2 HEAD --statএটা কিছুই ছাপে না: রিভার্টের পরের কোড খারাপ কমিটের আগের কোডের হুবহু এক।
আনট্র্যাকড ফাইল ফেলা: git clean
git restore আর git reset শুধু Git যে ফাইল ট্র্যাক করে সেগুলোতেই হাত দেয়। আগের স্ক্র্যাচ নোটবুকের মতো আনট্র্যাকড ফাইল যেমন ছিল তেমনই থাকে। git clean সেগুলো মুছে দেয়; আগে সবসময় -n দিয়ে ড্রাই রান করুন, কারণ মুছে ফেলা আনট্র্যাকড ফাইল চিরতরে চলে যায়:
git clean -n
git clean -f
git status --shortWould remove scratch.ipynb
Removing scratch.ipynbআনট্র্যাকড ফোল্ডারও মুছতে চাইলে -d যোগ করুন। ইগনোর করা ফাইল (আপনার .env, .venv/) -x না দিলে থেকে যায়; git clean -fdx নিয়ে বাড়তি সতর্ক থাকার এটাও একটা কারণ।
টিউটোরিয়ালে দেখা পুরোনো কমান্ড
Git 2.23-এর আগে একটাই কমান্ড, git checkout, ব্রাঞ্চ বদলানো এবং ফাইল ফেরানো করত, যা সবাইকে গুলিয়ে দিত। git switch আর git restore সেটাকে দুই ভাগ করেছে, এবং Git 2.51 থেকে এগুলো আনুষ্ঠানিকভাবে স্থিতিশীল। Stack Overflow-এর উত্তর আর পুরোনো টিউটোরিয়ালে এখনো পুরোনো রূপগুলো দেখবেন:
| পুরোনো রূপ | আধুনিক রূপ | মানে |
|---|---|---|
git checkout -- words.py | git restore words.py | ওয়ার্কিং ট্রির এডিট ফেলে দেওয়া |
git reset HEAD words.py | git restore --staged words.py | আনস্টেজ করা |
git checkout abc1234 -- words.py | git restore --source=abc1234 --staged --worktree words.py | পুরোনো কমিট থেকে ফাইল আনা |
git checkout -b feature | git switch -c feature | ব্রাঞ্চ বানিয়ে তাতে সুইচ করা (পরের পাতায়) |
আমি কী আনডু করতে চাই?
| পরিস্থিতি | কমান্ড | কাজ হারায়? |
|---|---|---|
| ফাইল এডিট করেছি, কমিট করা সংস্করণ ফেরত চাই | git restore FILE | হ্যাঁ, এডিটগুলো |
| পরের কমিটে চাই না এমন ফাইল স্টেজ করে ফেলেছি | git restore --staged FILE | না |
| একটা ফাইলের পুরোনো সংস্করণ চাই | git restore --source=COMMIT FILE | ওই ফাইলের বর্তমান এডিট ওভাররাইট হয় |
| শেষ কমিট মেসেজে বানান ভুল (পুশ করা হয়নি) | git commit --amend -m "…" | না |
| শেষ কমিটে ফাইল দিতে ভুলে গেছি (পুশ করা হয়নি) | git add FILE, git commit --amend --no-edit | না |
| শেষ কয়েকটা কমিট আনডু, পরিবর্তন রেখে (পুশ করা হয়নি) | git reset --soft HEAD~N বা git reset HEAD~N | না |
| শেষ কয়েকটা কমিট আর সব এডিট ফেলে দেওয়া (পুশ করা হয়নি) | git reset --hard HEAD~N | হ্যাঁ (কমিট কিছুদিন reflog থেকে ফেরানো যায়) |
| পুশ হয়ে যাওয়া কমিট আনডু | git revert COMMIT | না, নতুন কমিট যোগ হয় |
| আনট্র্যাকড ফাইল মোছা | git clean -n, তারপর git clean -f | হ্যাঁ |
বাস্তব AI কাজে কোথায় লাগে
- এক্সপেরিমেন্ট: প্রম্পট, ফিচার লিস্ট বা থ্রেশহোল্ড বদলালেন, ইভ্যালুয়েশন স্কোর কমে গেল, আর
git restoreএক কমান্ডে আপনাকে ভালো সংস্করণে ফিরিয়ে নিল। এজন্যই প্রতিটা এক্সপেরিমেন্টের আগে কমিট করতে হয়। - ভুল করে স্টেজ করা:
git add .নোটবুক, আউটপুট CSV আর মডেল ফাইলও টেনে নেয়; কমিটের আগেgit restore --staged(এবং একটা ভালো.gitignore) সেগুলো বাইরে রাখে। - প্রোডাকশন রোলব্যাক: মার্জ করা কোনো পরিবর্তনের কারণে ডিপ্লয় করা মডেল API উল্টাপাল্টা চললে টিমগুলো
mainনতুন করে না লিখে মার্জটাgit revertকরে আবার ডিপ্লয় করে। ঠিক করার কাজটা তারপর শান্তভাবে একটা ব্রাঞ্চে হয়। - পরিষ্কার পুল রিকোয়েস্ট: ব্রাঞ্চ পুশ করার আগে ডেভেলপাররা
--amendআরreset --softদিয়ে লোকাল কমিট গুছিয়ে নেয়, যাতে রিভিউয়াররা একটা পরিষ্কার গল্প দেখতে পায়।
সাধারণ ভুল
- কমিট না করা কাজ থাকা অবস্থায়
git reset --hardচালানো। ট্র্যাক করা ফাইলের সব এডিট উধাও হয়, reflog-ও সাহায্য করতে পারে না। সমাধান: আগেgit status; যা লাগতে পারে তা কমিট বা স্ট্যাশ করুন। - পুশ হয়ে যাওয়া কমিট অ্যামেন্ড বা রিসেট করা। আপনার পরের পুশ প্রত্যাখ্যাত হয়, আর জোর করে পুশ করলে সহকর্মীদের হিস্ট্রি নতুন করে লেখা হয়। সমাধান: শেয়ার করা কমিটের জন্য
git revert। --stagedভুলে গিয়েgit restore FILEচালানো। আনস্টেজ করতে চেয়েছিলেন, কিন্তু এডিটগুলোই ফেলে দিলেন। সমাধান: কমান্ডটা দুইবার পড়ুন;--staged-ই নিরাপদটা।- ভাবা যে
git resetবাgit restoreনতুন ফাইল সরাবে। এগুলো শুধু ট্র্যাক করা ফাইলে হাত দেয়; আনট্র্যাকড ফাইল থেকে যায়। সমাধান: দেখতেgit clean -n, তারপরgit clean -f। - খারাপ রিসেটের পর ঘাবড়ে যাওয়া। কমিট করা কাজ প্রায় কখনোই হারায় না। সমাধান:
git reflogদেখে কমিটটা খুঁজে নিন, তারপরgit reset --hard HASH(অথবা সেখানে একটা ব্রাঞ্চ বানান)।
নিজে চেষ্টা করুন
একই রিপোজিটরিতে, ক্রমানুসারে চালিয়ে যান।
- সহজ:
reviews.csvওভাররাইট করে শুধু হেডার লাইন রাখুন (যেমন একটা বাগি স্ক্রিপ্ট করত),git diff --statদিয়ে ক্ষতিটা দেখুন, তারপর কমিট করা সংস্করণ ফিরিয়ে এনে তার লাইন গুনুন। - মাঝারি: positive শব্দে "awesome" যোগ করে
wipমেসেজে কমিট করুন। কনটেন্ট না বদলে সেই কমিটকে এমন একটা কমিট দিয়ে বদলান যার মেসেজAdd awesome to positive words,git reset --softদিয়ে (--amendনয়)। - কঠিন: ধরুন "awesome" কমিটটা পুশ হয়ে গেছে এবং সবার জন্য আনডু করতে হবে। শেয়ার করা হিস্ট্রির নিয়মে সেটা আনডু করুন, তারপর দেখান যে
words.py-তে "awesome" আর নেই এবং মূল কমিটটা এখনো লগে আছে।
উত্তর
# সহজ
echo "id,text" > reviews.csv
git diff --stat
git restore reviews.csv
wc -l reviews.csv reviews.csv | 4 ----
1 file changed, 4 deletions(-)
5 reviews.csv# মাঝারি
cat > words.py <<'EOF'
POSITIVE = {"good", "great", "fast", "love", "awesome"}
NEGATIVE = {"bad", "slow", "broken", "late", "terrible"}
EOF
git commit -q -am "wip"
git reset --soft HEAD~1
git commit -q -m "Add awesome to positive words"
git log --oneline -2b3455ab Add awesome to positive words
13c3fa4 Revert "Count fine as positive"# কঠিন
git revert --no-edit HEADgrep -c awesome words.py
git log --oneline -30
11d2063 Revert "Add awesome to positive words"
b3455ab Add awesome to positive words
13c3fa4 Revert "Count fine as positive"grep -c মিলে যাওয়া লাইন গোনে: ০টা। লগে পরিবর্তন আর তার রিভার্ট দুটোই থাকে, তাই শেয়ার করা হিস্ট্রি কখনো নতুন করে লেখা হয় না।
সারসংক্ষেপ
- প্রথমে ঠিক করুন ভুলটা কোথায়: ওয়ার্কিং ট্রি, স্টেজিং এরিয়া, লোকাল কমিট, নাকি শেয়ার করা হিস্ট্রি।
git restore FILEএডিট ফেলে দেয় (চিরতরে);git restore --staged FILEআনস্টেজ করে কিন্তু এডিট রেখে দেয়;--source=COMMITপুরোনো সংস্করণ আনে।git commit --amendশেষ কমিটের মেসেজ বা কনটেন্ট ঠিক করে; এটা নতুন কমিট বানায়, তাই শুধু পুশের আগে ব্যবহার করুন।git resetব্রাঞ্চ পিছিয়ে নেয়:--softপরিবর্তন স্টেজড রাখে,--mixedএডিট হিসেবে রাখে,--hardফেলে দেয়। reflog কমিট ফেরাতে পারে, কমিট-না-করা এডিট কখনো নয়।- পুশ হয়ে যাওয়া যেকোনো কিছুর জন্য
git revertহিস্ট্রি নতুন না লিখে এমন একটা নতুন কমিট যোগ করে, যা পুরোনো কমিটকে আনডু করে।
এরপর: ব্রাঞ্চ, মার্জ ও মার্জ কনফ্লিক্ট। main-এ এক্সপেরিমেন্ট আনডু করার বদলে এবার ব্রাঞ্চে সেগুলো চালাবেন, যেগুলো কাজ করে সেগুলো মার্জ করবেন, আর আপনার প্রথম মার্জ কনফ্লিক্ট মেটাবেন।