অধ্যায় 2 · Git ও GitHub
কমিট, হিস্ট্রি ও ডিফ
- পৃষ্ঠা 5 / 22
- 17 মিনিট পড়া
একটা রিপোজিটরি তখনই কাজের, যখন তার হিস্ট্রি পড়ে বোঝা যায়। ছয় মাস পর কেউ — খুব সম্ভব আপনি নিজেই — জানতে চাইবে ক্লাসিফায়ার কেন নিরপেক্ষ রিভিউকে নেগেটিভ বলতে শুরু করল, কোন পরিবর্তনে API ধীর হয়ে গেল, কিংবা ইভ্যালুয়েশন স্কোর সবচেয়ে ভালো থাকার সময় প্রম্পটটা কেমন ছিল। উত্তরগুলো কমিটের মধ্যেই আছে — যদি কমিট মেসেজে কিছু লেখা থাকে আর আপনি সেগুলো খুঁজতে জানেন।
এই পাতায় আমরা ভার্সন কন্ট্রোল ও আপনার প্রথম রিপোজিটরি পাতার sentiment-api রিপোজিটরি নিয়েই এগোব। আপনি এমন কমিট মেসেজ লিখতে শিখবেন যা নিজেই নিজেকে ব্যাখ্যা করে, git log আর git show দিয়ে হিস্ট্রি পড়বেন, git diff দিয়ে ঠিক কী বদলেছে দেখবেন, আর শেষে একটা কমিটের ভেতরটা খুলে দেখবেন সেটা আসলে কী।
যা শিখবেন
- ভালো কমিট মেসেজ লেখা: ছোট, আদেশসূচক (imperative) একটা সাবজেক্ট, আর দরকার হলে "কেন" ব্যাখ্যা করা একটা বডি
git log(--oneline,--graph,--stat,-p, ফিল্টার) আরgit showদিয়ে হিস্ট্রি পড়াgit diffদিয়ে পরিবর্তন দেখা: আনস্টেজড, স্টেজড (--staged) আর যেকোনো দুটো কমিটের মধ্যে- কমিটের নাম দেওয়া: হ্যাশ,
HEAD,HEAD~1 - কমিটের ভেতরে কী আছে: একটা স্ন্যাপশট (ট্রি), তার প্যারেন্ট, লেখক, মেসেজ — আর এই সবকিছু থেকে হিসাব করা হ্যাশ
আগের অবস্থায় ফেরা
আগের পাতা অনুসরণ করে থাকলে cd ~/projects/sentiment-api দিয়ে চালিয়ে যান। না করে থাকলে নিচের ব্লকটা একই চারটা কমিটসহ একই রিপোজিটরি আবার বানিয়ে দেবে (-q Git-কে চুপ রাখে):
mkdir -p ~/projects/sentiment-api
cd ~/projects/sentiment-api
git init -q
cat > README.md <<'EOF'
# Sentiment API
A tiny sentiment classifier for course reviews, growing into a web API.
EOF
git add README.md
git commit -q -m "Add README"
cat > sentiment.py <<'EOF'
"""A tiny rule-based sentiment classifier: our stand-in for a real model."""
POSITIVE = {"good", "great", "clear", "love", "loved"}
NEGATIVE = {"bad", "hard", "slow", "confusing"}
def classify(text: str) -> str:
words = set(text.lower().replace(",", " ").split())
score = len(words & POSITIVE) - len(words & NEGATIVE)
if score > 0:
return "positive"
if score < 0:
return "negative"
return "neutral"
if __name__ == "__main__":
for review in ["Great course, loved it", "Setup was hard", "It was okay"]:
print(f"{review!r}: {classify(review)}")
EOF
git add sentiment.py
git commit -q -m "Add rule-based sentiment classifier"
cat >> README.md <<'EOF'
## Usage
python3 sentiment.py
EOF
git commit -q -a -m "Document how to run the classifier"
echo "Reviews come from the BitByte courses." >> README.md
git commit -q -a -m "Describe the data"
git log --oneline24c4e9d Describe the data
1b5d9ca Document how to run the classifier
7d030ed Add rule-based sentiment classifier
faa9787 Add READMEআপনার হ্যাশগুলো এই পাতার হ্যাশ থেকে আলাদা হবে — এটাই স্বাভাবিক। কমিটের হ্যাশ হিসাব হয় অন্য অনেক কিছুর সাথে লেখক আর কমিটের ঠিক সময় থেকেও, তাই একই কমান্ড টাইপ করলেও দুজনের হ্যাশ আলাদা হয়। হ্যাশে ঠিক কী কী ঢোকে তা এই পাতার শেষে দেখানো হয়েছে।
কাজের কমিট মেসেজ লেখা
কমিট মেসেজে থাকে একটা সাবজেক্ট লাইন আর ঐচ্ছিক একটা বডি, মাঝখানে একটা ফাঁকা লাইন। বেশিরভাগ প্রজেক্টের প্রচলিত নিয়ম:
- সাবজেক্ট আদেশসূচক ভঙ্গিতে, প্রায় ৫০ অক্ষরের, শেষে দাঁড়ি ছাড়া: "Add retry to the weather client" — যেন "If applied, this commit will …" বাক্যটা সম্পূর্ণ করছেন। Git নিজেও এভাবেই মেসেজ লেখে ("Merge branch …", "Revert …")।
- বডিতে "কেন" লিখুন, "কীভাবে" নয়: কীভাবে বদলেছে তা ডিফেই দেখা যায়। বডিতে লিখুন কোন সমস্যা মিটছে, কেন এই পথ নেওয়া হলো, আর অবাক করার মতো কিছু থাকলে সেটা। প্রায় ৭২ অক্ষরে লাইন ভাঙুন।
- এক কমিটে একটাই যুক্তিসংগত পরিবর্তন: একটা বাগ ফিক্স আর পুরো ফাইলের ফরম্যাটিং বদল দুটো আলাদা কমিট। ছোট, একমুখী কমিট রিভিউ করা, খুঁজে পাওয়া আর ফেরত নেওয়া সহজ।
| দুর্বল মেসেজ | ভালো মেসেজ | কেন ভালো |
|---|---|---|
update | Add negative words for setup problems | কী বদলেছে বলে দেয় |
fixed bug | Handle empty reviews in classify() | কোন বাগ, কোথায় — বলে দেয় |
changes to prompt | Ask the model to answer in Bangla when the question is in Bangla | ডিফ না খুলেই আচরণের পরিবর্তন বোঝা যায় |
WIP, asdf, final | Lower spam threshold from 0.8 to 0.7 + ইভ্যাল ফলাফলসহ একটা বডি | সিদ্ধান্ত আর তার প্রমাণ দুটোই লেখা থাকে |
কিছু টিম Conventional Commits-ও ব্যবহার করে — একটা প্রিফিক্স, যা বলে দেয় পরিবর্তনটা কেমন ধরনের: feat: add /predict endpoint, fix: handle empty reviews, docs: …, test: …। তখন টুল দিয়ে হিস্ট্রি থেকে চেঞ্জলগ বানানো যায়। আপনার টিম যা মানে, তা-ই মানুন; নিজের প্রজেক্টে পরিষ্কার একটা আদেশসূচক সাবজেক্টই যথেষ্ট।
কী বদলেছে দেখা: git diff
ক্লাসিফায়ার কিছু সাধারণ শব্দ চেনে না। sentiment.py খুলে দুটো শব্দতালিকা বাড়ান, যাতে ফাইলটা নিচের মতো হয়:
cat > sentiment.py <<'EOF'
"""A tiny rule-based sentiment classifier: our stand-in for a real model."""
POSITIVE = {"good", "great", "clear", "love", "loved", "excellent", "useful"}
NEGATIVE = {"bad", "hard", "slow", "confusing", "boring", "buggy"}
def classify(text: str) -> str:
words = set(text.lower().replace(",", " ").split())
score = len(words & POSITIVE) - len(words & NEGATIVE)
if score > 0:
return "positive"
if score < 0:
return "negative"
return "neutral"
if __name__ == "__main__":
for review in ["Great course, loved it", "Setup was hard", "It was okay"]:
print(f"{review!r}: {classify(review)}")
EOFকমিট করার আগে দেখে নিন ঠিক কী বদলেছেন। কোনো আর্গুমেন্ট ছাড়া git diff ওয়ার্কিং ট্রি আর স্টেজিং এরিয়ার তুলনা করে — অর্থাৎ এখনো স্টেজ করেননি এমন পরিবর্তনগুলো দেখায়:
git diffdiff --git a/sentiment.py b/sentiment.py
index a8bd313..a2307bd 100644
--- a/sentiment.py
+++ b/sentiment.py
@@ -1,7 +1,7 @@
"""A tiny rule-based sentiment classifier: our stand-in for a real model."""
-POSITIVE = {"good", "great", "clear", "love", "loved"}
-NEGATIVE = {"bad", "hard", "slow", "confusing"}
+POSITIVE = {"good", "great", "clear", "love", "loved", "excellent", "useful"}
+NEGATIVE = {"bad", "hard", "slow", "confusing", "boring", "buggy"}
def classify(text: str) -> str:ডিফ পড়ার নিয়ম:
--- a/…পুরোনো সংস্করণ,+++ b/…নতুন সংস্করণ।@@ -1,7 +1,7 @@হলো হাঙ্ক হেডার (hunk header): এই অংশ ১ নম্বর লাইন থেকে শুরু, আর পুরোনো ও নতুন দুই ফাইলেই ৭ লাইন লম্বা। শুধু বদলানো এলাকাটা দেখানো হয়, আশেপাশে সর্বোচ্চ তিন লাইন অপরিবর্তিত প্রসঙ্গ (context) সহ।-দিয়ে শুরু লাইন মুছেছে,+দিয়ে শুরু লাইন যোগ হয়েছে। Git পুরো লাইন ধরে কাজ করে, তাই একটা শব্দ বদলালে দেখায় একটা লাইন মুছেছে আর একটা যোগ হয়েছে।
এবার পরিবর্তনটা স্টেজ করে আবার git diff চালান:
git add sentiment.py
git diff
echo "--- staged:"
git diff --staged --stat--- staged:
sentiment.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)সাধারণ git diff কিছুই দেখাল না — কিছু বদলায়নি বলে নয়, বরং সবকিছু এখন স্টেজড। git diff --staged (--cached-এর মতোই) স্টেজিং এরিয়াকে শেষ কমিটের সাথে তুলনা করে: অর্থাৎ "আমি যে কমিটটা করতে যাচ্ছি তাতে কী যাবে"। --stat প্রতিটা লাইন না দেখিয়ে সারসংক্ষেপ দেয়। প্রতিটা কমিটের ঠিক আগে git diff --staged চালানোর অভ্যাস অনেক দুর্ঘটনা ধরে ফেলে।
এবার সাবজেক্ট আর বডিসহ কমিট করুন। প্রতিটা -m একটা করে প্যারাগ্রাফ যোগ করে, তাই দুটো -m মানে সাবজেক্ট আর বডি:
git commit -m "Recognise more sentiment words" -m "Reviews often say \"excellent\", \"useful\", \"boring\" or \"buggy\", and the
classifier marked them neutral. Adding them fixes 4 of the 6 wrong
labels in last week's sample."[main 7e92094] Recognise more sentiment words
1 file changed, 2 insertions(+), 2 deletions(-)লম্বা মেসেজের জন্য -m ছাড়া git commit চালান: Git আপনার এডিটর (আগের পাতার core.editor) খুলবে, স্টেজড পরিবর্তনগুলো কমেন্ট আকারে দেখিয়ে। প্রথম লাইনে সাবজেক্ট লিখুন, তারপর একটা ফাঁকা লাইন, তারপর বডি; সেভ করে বন্ধ করলেই কমিট হবে, আর মেসেজ ফাঁকা রাখলে কমিট বাতিল হবে।
আরও একটা কমিট করি, যেটা দুটো ফাইল ছোঁয়, যাতে হিস্ট্রিতে দেখার মতো কিছু থাকে:
mkdir -p data
cat > data/sample_reviews.txt <<'EOF'
Excellent examples, very useful
The videos were boring
Setup was hard and the notebook was buggy
Good pace
EOF
cat >> README.md <<'EOF'
Sample reviews for manual checks are in data/sample_reviews.txt.
EOF
git add data/sample_reviews.txt README.md
git commit -q -m "Add sample reviews for manual testing"
git log --oneline951898f Add sample reviews for manual testing
7e92094 Recognise more sentiment words
24c4e9d Describe the data
1b5d9ca Document how to run the classifier
7d030ed Add rule-based sentiment classifier
faa9787 Add READMEহিস্ট্রি পড়া: git log
সাধারণ git log প্রতিটা কমিট পুরোটা দেখায়, নতুনটা আগে:
git log -n 2commit 951898fcc84b264e32efe1ec5b04eddc98b0d5f5
Author: Nadia Rahman <nadia@example.com>
Date: Thu Jan 15 10:00:00 2026 +0600
Add sample reviews for manual testing
commit 7e92094399af689cba406cde21051b4af78d6aa0
Author: Nadia Rahman <nadia@example.com>
Date: Thu Jan 15 10:00:00 2026 +0600
Recognise more sentiment words
Reviews often say "excellent", "useful", "boring" or "buggy", and the
classifier marked them neutral. Adding them fixes 4 of the 6 wrong
labels in last week's sample.প্রতিটা এন্ট্রিতে আছে ৪০ অক্ষরের পূর্ণ হ্যাশ, লেখক, তারিখ আর পুরো মেসেজ। (আসল টার্মিনালে লম্বা লগ একটা পেজার-এ খোলে: তীরচিহ্ন বা Space দিয়ে স্ক্রল করুন, /শব্দ দিয়ে খুঁজুন, বের হতে q চাপুন।) সবচেয়ে বেশি কাজে লাগবে যে অপশনগুলো:
| কমান্ড | কী দেখায় |
|---|---|
git log --oneline | প্রতি কমিটে এক লাইন: ছোট হ্যাশ আর সাবজেক্ট |
git log -n 3 | শুধু শেষ ৩টা কমিট |
git log --stat | প্রতিটা কমিট কোন ফাইল কতটা বদলেছে |
git log -p | প্রতিটা কমিটের পূর্ণ ডিফ |
git log --graph --oneline --all | সব ব্রাঞ্চসহ হিস্ট্রি একটা গ্রাফ হিসেবে |
git log -- sentiment.py | শুধু যে কমিটগুলো এই ফাইল বদলেছে |
git log --grep="sample" | যে কমিটের মেসেজে একটা শব্দ আছে |
git log --author="Nadia" | একজন ব্যক্তির কমিট |
git log --stat -n 2
echo "--- commits that changed sentiment.py:"
git log --oneline -- sentiment.py
echo "--- messages mentioning 'sample':"
git log --oneline --grep="sample"commit 951898fcc84b264e32efe1ec5b04eddc98b0d5f5
Author: Nadia Rahman <nadia@example.com>
Date: Thu Jan 15 10:00:00 2026 +0600
Add sample reviews for manual testing
README.md | 1 +
data/sample_reviews.txt | 4 ++++
2 files changed, 5 insertions(+)
commit 7e92094399af689cba406cde21051b4af78d6aa0
Author: Nadia Rahman <nadia@example.com>
Date: Thu Jan 15 10:00:00 2026 +0600
Recognise more sentiment words
Reviews often say "excellent", "useful", "boring" or "buggy", and the
classifier marked them neutral. Adding them fixes 4 of the 6 wrong
labels in last week's sample.
sentiment.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- commits that changed sentiment.py:
7e92094 Recognise more sentiment words
7d030ed Add rule-based sentiment classifier
--- messages mentioning 'sample':
951898f Add sample reviews for manual testing
7e92094 Recognise more sentiment words--grep দুটো কমিট পেয়েছে: একটার সাবজেক্টে "sample" আছে, আরেকটায় শব্দটা শুধু বডিতে ("last week's sample")। বডি লেখার এটা একটা ছোট কারণ — বডিও খোঁজা যায়।
--graph হিস্ট্রিকে গ্রাফ হিসেবে আঁকে। আমাদেরটা সোজা একটা রেখা, কারণ ব্রাঞ্চ একটাই; ব্রাঞ্চ, মার্জ ও মার্জ কনফ্লিক্ট পাতায় একই কমান্ডে রেখা ভাগ হতে আর জোড়া লাগতে দেখবেন। --format দিয়ে কোন ফিল্ড দেখাবেন তা নিজে ঠিক করা যায়:
git log --graph --oneline --all
git log --format="%h %ad %an %s" --date=short -n 3* 951898f Add sample reviews for manual testing
* 7e92094 Recognise more sentiment words
* 24c4e9d Describe the data
* 1b5d9ca Document how to run the classifier
* 7d030ed Add rule-based sentiment classifier
* faa9787 Add README
951898f 2026-01-15 Nadia Rahman Add sample reviews for manual testing
7e92094 2026-01-15 Nadia Rahman Recognise more sentiment words
24c4e9d 2026-01-15 Nadia Rahman Describe the data(%h ছোট হ্যাশ, %ad লেখকের তারিখ, %an লেখকের নাম, %s সাবজেক্ট। আমাদের সব তারিখ একই, কারণ এই পাতার কমিটগুলো একটা নির্দিষ্ট ঘড়িতে করা হয়েছে; আপনারটায় আপনি যখন করেছেন সেই সময় দেখাবে।)
কমিটের নাম দেওয়া: হ্যাশ আর HEAD
যে কমান্ড কমিট নেয়, সেটা কয়েক ধরনের নাম মানে:
| নাম | মানে |
|---|---|
a2f6c1e (হ্যাশের যেকোনো অনন্য শুরুর অংশ) | সেই কমিট। সাধারণত সাত অক্ষরই যথেষ্ট। |
HEAD | আপনি এখন যে কমিটে আছেন (বর্তমান ব্রাঞ্চের সর্বশেষটা) |
HEAD~1 (বা HEAD^) | তার প্যারেন্ট, এক কমিট পিছনে |
HEAD~3 | তিন কমিট পিছনে |
main | main ব্রাঞ্চের সর্বশেষ কমিট |
git show একটা কমিট দেখায় — তার মেসেজ আর ডিফ। commit:path দিলে সেই কমিটে ফাইলটা যেমন ছিল তেমন দেখায়, আপনার ওয়ার্কিং ট্রিতে কিছু না বদলিয়ে:
git show HEAD~1
echo "--- README.md three commits ago:"
git show HEAD~3:README.mdcommit 7e92094399af689cba406cde21051b4af78d6aa0
Author: Nadia Rahman <nadia@example.com>
Date: Thu Jan 15 10:00:00 2026 +0600
Recognise more sentiment words
Reviews often say "excellent", "useful", "boring" or "buggy", and the
classifier marked them neutral. Adding them fixes 4 of the 6 wrong
labels in last week's sample.
diff --git a/sentiment.py b/sentiment.py
index a8bd313..a2307bd 100644
--- a/sentiment.py
+++ b/sentiment.py
@@ -1,7 +1,7 @@
"""A tiny rule-based sentiment classifier: our stand-in for a real model."""
-POSITIVE = {"good", "great", "clear", "love", "loved"}
-NEGATIVE = {"bad", "hard", "slow", "confusing"}
+POSITIVE = {"good", "great", "clear", "love", "loved", "excellent", "useful"}
+NEGATIVE = {"bad", "hard", "slow", "confusing", "boring", "buggy"}
def classify(text: str) -> str:
--- README.md three commits ago:
# Sentiment API
A tiny sentiment classifier for course reviews, growing into a web API.
## Usage
python3 sentiment.pyযেকোনো দুটো কমিটের তুলনা
git diff A B দেখায় A থেকে B পর্যন্ত কী বদলেছে। কিছু ফাইলে সীমিত রাখতে -- path যোগ করুন, আর সারসংক্ষেপের জন্য --stat:
git diff --stat HEAD~3 HEAD
echo "---"
git diff HEAD~2 HEAD -- README.md README.md | 2 ++
data/sample_reviews.txt | 4 ++++
sentiment.py | 4 ++--
3 files changed, 8 insertions(+), 2 deletions(-)
---
diff --git a/README.md b/README.md
index 1390352..c2e74a7 100644
--- a/README.md
+++ b/README.md
@@ -6,3 +6,4 @@ A tiny sentiment classifier for course reviews, growing into a web API.
python3 sentiment.py
Reviews come from the BitByte courses.
+Sample reviews for manual checks are in data/sample_reviews.txt.ক্রম গুরুত্বপূর্ণ: git diff HEAD~2 HEAD HEAD~2-এর পর যোগ হওয়া লাইনগুলো + দিয়ে দেখায়; দুটো উল্টে দিলে একই লাইনগুলো - দিয়ে আসবে। এভাবেই আপনি উত্তর দেবেন "যে রিলিজে স্কোর ভালো ছিল আর আজকের মধ্যে প্রম্পটে কী বদলেছে?" — git log-এ দুটো কমিট খুঁজে নিন, তারপর প্রম্পট ফাইলে সীমিত করে git diff চালান।
কমিট আসলে কী
git log আর git diff দেখে মনে হয় Git বুঝি পরিবর্তন জমা রাখে। আসলে সে রাখে স্ন্যাপশট, আর ডিফ হিসাব করে আপনি চাইলে। git cat-file -p Git-এর কাঁচা অবজেক্ট ছাপে, ফলে ভেতরটা দেখা যায়:
git cat-file -p HEADtree 614f68153b9880f758fd84a600fb71f11fcca53f
parent 7e92094399af689cba406cde21051b4af78d6aa0
author Nadia Rahman <nadia@example.com> 1768449600 +0600
committer Nadia Rahman <nadia@example.com> 1768449600 +0600
Add sample reviews for manual testingপুরো কমিট এটুকুই:
- tree — এই মুহূর্তে পুরো প্রজেক্ট ফোল্ডারের একটা স্ন্যাপশটের হ্যাশ;
- parent — আগের কমিটের হ্যাশ (প্রথম কমিটের প্যারেন্ট নেই; মার্জ কমিটের দুটো);
- author আর committer — নাম, ইমেইল, ১ জানুয়ারি ১৯৭০ থেকে সেকেন্ডে সময়, আর টাইম জোন (
+0600বাংলাদেশ সময়); - আর মেসেজ।
ট্রি ফাইল আর ফোল্ডারের তালিকা দেয়, প্রতিটা হ্যাশ দিয়ে আরেকটা অবজেক্টকে নির্দেশ করে। ব্লব (blob) হলো ফাইলের বিষয়বস্তু:
git cat-file -p HEAD^{tree}
echo "---"
git cat-file -p HEAD:data100644 blob c2e74a78a3e118dff236b00d2b0977c75f8cb6ef README.md
040000 tree b8e4632751c6b9a2b848db88a6e0e01ed508966e data
100644 blob a2307bd19ca9f3c2ffc4ce463c48da041f8b08cc sentiment.py
---
100644 blob 6f3d65bcb322c260ee740242baf3652a6b63a18c sample_reviews.txtএই প্রতিটা হ্যাশ অবজেক্টের বিষয়বস্তুর SHA-1 চেকসাম। তাই কমিটের হ্যাশ নির্ভর করে তার ট্রির (সব ফাইল), প্যারেন্টের হ্যাশের (ফলে তার আগের পুরো হিস্ট্রির), লেখকের, সময়ের আর মেসেজের উপর। কোথাও একটা বাইট বদলালে তার পরের প্রতিটা হ্যাশ বদলে যায়। এ কারণেই Git-এর হিস্ট্রি চুপিসারে বদলানো যায় না, একই দুটো কমিট আলাদা সময়ে করলে হ্যাশ আলাদা হয়, আর এই পাতার সাথে আপনার হ্যাশ মেলে না।
অন্যদিকে ফাইলের বিষয়বস্তুর হ্যাশ সব জায়গায় একই। চালিয়ে দেখুন — যে-ই চালাক, একই ৪০ অক্ষর পাবে:
echo "hello" | git hash-object --stdince013625030ba8dba906f756967f9e9ca394464aএখন পর্যন্ত পুরো হিস্ট্রি Git যেভাবে দেখে:
commit 1 commit 2 commit 3 ... commit 6 <-- main <-- HEAD
"Add README" <--- "Add rule- <---- "Document ... "Add sample
based ..." how ..." reviews ..."
| | | |
tree tree tree tree
| | | / | \
README.md README.md README.md README.md | data/
(blob) sentiment.py sentiment.py sentiment.py sample_reviews.txt
Each commit points back to its parent. Unchanged files are not copied:
trees in different commits point to the same blob.স্ন্যাপশট জমানো অপচয় মনে হতে পারে, কিন্তু তা নয়: যে ফাইল বদলায়নি সেটা একই ব্লব, একবারই জমা থাকে এবং যত ট্রিতে আছে সবাই শেয়ার করে, আর Git সবকিছু কম্প্রেস করে রাখে। এই নকশার জন্যই এক সংস্করণ বা ব্রাঞ্চ থেকে আরেকটায় যাওয়া প্রায় সঙ্গে সঙ্গে হয়।
AI আর ব্যাকএন্ডের কাজে এটা কোথায় লাগে
- রিগ্রেশন ডিবাগ: কোনো মেট্রিক নেমে গেলে বা এন্ডপয়েন্ট ভাঙলে সংশ্লিষ্ট ফাইলে
git log -p -- path, কিংবা শেষ ভালো আর প্রথম খারাপ রিলিজের মধ্যেgit diff, সাধারণত সরাসরি কারণে পৌঁছে দেয়। - প্রম্পট ও কনফিগের হিস্ট্রি: প্রম্পট ফাইলে রাখলে
git log --oneline -- prompts/হলো আপনার LLM-এর নির্দেশনা কীভাবে বিবর্তিত হয়েছে তার পূর্ণ ইতিহাস, প্রতিটা পরিবর্তনের কারণসহ। - কোড রিভিউ: পুল রিকোয়েস্ট (এই অধ্যায়ের পরের দিকে) আসলে আলোচনাসহ ডিফ; ডিফ সাবলীলভাবে পড়তে পারা কোড রিভিউয়ের অর্ধেক কাজ।
- ট্রেসেবিলিটি: প্রতিটা ট্রেনিং রান বা ডিপ্লয় করা API সংস্করণের সাথে কমিট হ্যাশ (
git rev-parse --short HEAD) লগ করলে প্রতিটা ফলাফল সেই ঠিক কোডের সাথে বাঁধা থাকে যা তাকে তৈরি করেছে।
সাধারণ ভুল
- "git diff কিছুই দেখাচ্ছে না, অথচ আমি ফাইল বদলেছি!" সম্ভবত পরিবর্তনগুলো আগেই স্টেজ হয়ে গেছে।
git diff --stagedব্যবহার করুন, বা কোথায় আছে দেখতেgit statusচালান। - "update" বা "fix"-এর মতো মেসেজ। এগুলো
git log-কে খোঁজার কাজে অকেজো করে দেয়। কী বদলেছে লিখুন, আর স্পষ্ট না হলে কেন বদলেছে তাও। - এক কমিটে সম্পর্কহীন পরিবর্তন মেশানো। একটা ফিচার, একটা বাগ ফিক্স আর ফরম্যাটিং এক কমিটে থাকলে আলাদাভাবে রিভিউ বা ফেরত নেওয়া যায় না।
git add <file>দিয়ে আলাদা স্টেজ করে কয়েকটা কমিট বানান। - নোটবুক তার সব আউটপুটসহ কমিট করা।
.ipynbফাইল আসলে JSON, যার ভেতরে আউটপুট, ছবি আর এক্সিকিউশন কাউন্ট থাকে; তাই তার ডিফ পড়া যায় না আর প্রতি রানে ফাইল বড় হয়। কমিটের আগে আউটপুট মুছুন (বা nbstripout-এর মতো টুল ব্যবহার করুন), আর যে কোড রাখবেন তা.pyফাইলে সরান। - পেজারে আটকে যাওয়া। লম্বা
git logবাgit diffআপনার স্ক্রলের অপেক্ষায় থাকে। প্রম্পট ফেরত পেতেqচাপুন।
নিজে চেষ্টা করুন
- সহজ: শেষ তিনটা কমিট এক লাইনের আকারে দেখান, তারপর শুধু সর্বশেষ কমিট যে ফাইলগুলো বদলেছে সেগুলো দেখান।
- মাঝারি:
sentiment.py-তেPOSITIVE-এhelpfulশব্দটা যোগ করুন (sedবা আপনার এডিটর দিয়ে)। কমিটের আগে স্টেজড ডিফ সংক্ষিপ্ত--statরূপে দেখান, তারপর একটা ভালো মেসেজসহ কমিট করুন। - কঠিন: সাবজেক্ট ও বডিসহ একটা কমিট বানান, তারপর
git log -1 --format=%bদিয়ে শুধু সর্বশেষ কমিটের বডি ছাপুন, আরgit show --name-only --format= HEADদিয়ে শুধু যে ফাইলগুলো সে ছুঁয়েছে সেগুলো ছাপুন।
উত্তর
১. -n 3 লগ সীমিত করে; git show --stat একটা কমিটের সারসংক্ষেপ দেয়:
git log --oneline -n 3
git show --stat --oneline HEAD951898f Add sample reviews for manual testing
7e92094 Recognise more sentiment words
24c4e9d Describe the data
951898f Add sample reviews for manual testing
README.md | 1 +
data/sample_reviews.txt | 4 ++++
2 files changed, 5 insertions(+)২. sed -i ফাইল জায়গায় বদলায় (macOS-এ sed -i '' লিখুন)। --stat লাইনটা নিশ্চিত করে ঠিক একটা লাইন বদলেছে:
sed -i 's/"excellent", "useful"}/"excellent", "useful", "helpful"}/' sentiment.py
git add sentiment.py
git diff --staged --stat
git commit -q -m "Treat 'helpful' as positive"
git log --oneline -n 1 sentiment.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
2efa0df Treat 'helpful' as positive৩. %b হলো বডি; ফাঁকা --format= কমিটের হেডার লুকিয়ে শুধু ফাইলের নামগুলো রাখে:
echo "Good pace, helpful mentors" >> data/sample_reviews.txt
git add data/sample_reviews.txt
git commit -q -m "Add a review that mentions mentors" -m "Covers the new 'helpful' word in manual checks."
git log -1 --format=%b
git show --name-only --format= HEADCovers the new 'helpful' word in manual checks.
data/sample_reviews.txtসারসংক্ষেপ
- কমিটের সাবজেক্ট আদেশসূচক ভঙ্গিতে, প্রায় ৫০ অক্ষরে লিখুন; স্পষ্ট না হলে "কেন" ব্যাখ্যা করে বডি যোগ করুন; এক কমিটে একটাই যুক্তিসংগত পরিবর্তন রাখুন।
git diffআনস্টেজড পরিবর্তন দেখায়,git diff --stagedযা কমিট করতে যাচ্ছেন তা দেখায়,git diff A Bযেকোনো দুটো কমিটের মধ্যের পরিবর্তন দেখায়।git logহিস্ট্রি পড়ে:--oneline,-n,--stat,-p,--graph --all,-- path,--grep,--author,--format।git showএকটা কমিট দেখায়, আরcommit:pathকোনো ফাইল সেই সময়ে যেমন ছিল তেমন দেখায়।- কমিটের নাম দিন হ্যাশ দিয়ে, বা
HEAD-এর সাপেক্ষে (HEAD~1,HEAD~3)। - কমিট হলো একটা স্ন্যাপশট (ট্রি) আর তার সাথে প্যারেন্ট, লেখক, কমিটার ও মেসেজ; হ্যাশ এই সবকিছুকে ঢেকে রাখে, তাই হিস্ট্রিতে হাত পড়লে ধরা পড়ে।
এরপর: .gitignore: সিক্রেট আর অপ্রয়োজনীয় ফাইল বাইরে রাখা — .env ফাইল, ভার্চুয়াল এনভায়রনমেন্ট, ক্যাশ, ডেটাসেট আর মডেল ফাইল যেন কখনো আপনার কমিটে না ঢোকে তা নিশ্চিত করবেন — আর জানবেন কেন একবার কমিট হওয়া সিক্রেট ফাঁস হয়ে গেছে ধরে নিতে হয়।