গাইড

git log, diff, show ও blame: Git-এ প্রকল্পের ইতিহাস কীভাবে পড়বেন

হালনাগাদ: · Skillaria.Top

git log কমিটের তালিকা দেখায় এবং লেখক, তারিখ, ফাইল ও লেখার ভিত্তিতে ছাঁকতে পারে; git diff কাজের ফোল্ডার, ইনডেক্স ও যেকোনো কমিটের পার্থক্য দেখায়; git show একটি কমিট পুরোটা দেখায়; git blame বলে দেয় কোন কমিট প্রতিটি লাইন শেষবার বদলেছে।

চারটি কমান্ড প্রকল্পের ইতিহাস সংক্রান্ত প্রায় সব প্রশ্নের উত্তর দেয়। git log বলে "কী ঘটেছিল", git diff বলে "ঠিক কী বদলেছে", git show বলে "একটি নির্দিষ্ট কমিটের ভেতরে কী আছে", আর git blame বলে "এই লাইনটি কে ও কখন লিখেছে"। নিচে প্রতিটির কাজের কৌশল দেওয়া হলো, যেসব ফ্ল্যাগ প্রতিদিনের কাজে সত্যিই ব্যবহার হয়।

git log: কমিটের তালিকা

কোনো আর্গুমেন্ট ছাড়া git log বর্তমান ব্রাঞ্চের কমিটগুলো নতুন থেকে পুরনোর দিকে দেখায়: পূর্ণ SHA-1 হ্যাশ, লেখক, তারিখ ও বার্তা। এটি পেজারে (সাধারণত less) খোলে: স্পেস — পরের পাতা, /লেখা — খোঁজা, q — বের হওয়া।

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Nusrat Jahan <nusrat@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: API প্রতিক্রিয়া ক্যাশ করা

হ্যাশ পুরোটা কপি করার দরকার নেই: Git যেকোনো অনন্য প্রিফিক্স বোঝে, সাধারণত ৭ অক্ষরই যথেষ্ট।

সংক্ষিপ্ত আউটপুট: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: API প্রতিক্রিয়া ক্যাশ করা
# 1c02e8f fix: অনুরোধের টাইমআউট ঠিক করা
# 9a4b3c2 refactor: ক্লায়েন্টকে আলাদা মডিউলে নেওয়া

-10 (বা -n 10) কমিটের সংখ্যা সীমিত করে। বন্ধনীতে থাকে পয়েন্টার: HEAD কোথায়, কোন লোকাল ও রিমোট ব্রাঞ্চ, কোন ট্যাগ।

ব্রাঞ্চের গ্রাফ: git log --graph

"git graph" খুঁজলে সাধারণত এটিই দরকার: টার্মিনালে শাখা ও মেশানোর ছবি।

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: টোকেন দিয়ে লগইন
# | * 7be41d0 (HEAD -> main) feat: API প্রতিক্রিয়া ক্যাশ করা
# |/
# * 1c02e8f fix: অনুরোধের টাইমআউট ঠিক করা
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: সার্চ
# |/
# * 9a4b3c2 refactor: ক্লায়েন্টকে আলাদা মডিউলে নেওয়া

--all সব ব্রাঞ্চ দেখায়, শুধু বর্তমানটি নয়। প্রায়ই ব্যবহার হয় বলে একটি অ্যালিয়াস বানান: git config --global alias.lg "log --oneline --graph --all --decorate", এরপর শুধু git lg।

নিজের ফরম্যাট: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Nusrat Jahan API প্রতিক্রিয়া ক্যাশ করা

মূল প্লেসহোল্ডার: %h — সংক্ষিপ্ত হ্যাশ, %H — পূর্ণ, %an — লেখক, %ae — তাঁর ইমেইল, %ad — লেখকের তারিখ, %ar — আপেক্ষিক তারিখ ("2 days ago"), %s — বার্তার শিরোনাম।

git log দিয়ে ইতিহাস ছাঁকা

লেখক ও তারিখ দিয়ে

git log --author="Nusrat"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author নিয়মিত অভিব্যক্তি নেয় এবং নাম ও ইমেইল দুটোতেই খোঁজে। তারিখ Git বোঝে মুক্ত আকারে এবং ISO ফরম্যাটে।

বার্তার লেখা দিয়ে

git log --grep="fix" -i --oneline

-i বড়-ছোট হাতের অক্ষর আলাদা করে না। দল যদি বার্তায় টাস্কের নম্বর লেখে, তাহলে এভাবে এক টাস্কের সব কমিট দ্রুত পাওয়া যায়।

ফাইল বা ফোল্ডার দিয়ে

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

দুটি ড্যাশ পথ আর ব্রাঞ্চকে আলাদা করে। --follow নাম বদলের মধ্য দিয়েও ফাইলের ইতিহাস চালিয়ে যায় (শুধু একটি ফাইলের জন্য কাজ করে), আর -p প্রতিটি কমিটের প্যাচ দেখায়।

কোডের পরিবর্তন দিয়ে: "পিকাক্স" খোঁজা

git log -S "retry_count" --oneline     # যে কমিটে স্ট্রিংয়ের সংখ্যা বদলেছে
git log -G "timeout\s*=" --oneline    # যে কমিটের diff-এ regex-এর মিল আছে

-S সেই কমিট খোঁজে, যেখানে কোনো ফাংশন বা ভ্যারিয়েবল যোগ বা বাদ হয়েছে। কোন কারণে কোডের একটি অংশ হারিয়ে গেল, তা বুঝতে এটি অপরিহার্য।

কমিটের পরিসর

git log main..feature      # feature-এ আছে, main-এ নেই
git log origin/main..HEAD  # আমার স্থানীয় কমিট, এখনো পাঠানো হয়নি
git log --no-merges        # merge কমিট বাদ দিয়ে
git log --stat             # কোন ফাইল কতটা বদলেছে

git diff: কী ঠিক বদলেছে

git diff-এর ক্ষেত্রে প্রথমে বোঝা দরকার কোন দুটি অবস্থা তুলনা করা হচ্ছে। এখানকার বিভ্রান্তিই প্রশ্নের কারণ: "diff খালি কেন, আমি তো সব বদলেছি!"।

কমান্ডকী তুলনা করে
git diffওয়ার্কিং ফোল্ডার বনাম ইনডেক্স (অপ্রস্তুত পরিবর্তন)
git diff --staged (--cached)ইনডেক্স বনাম সর্বশেষ কমিট (কমিটে কী যাবে)
git diff HEADওয়ার্কিং ফোল্ডার বনাম সর্বশেষ কমিট (সব একসঙ্গে)
git diff A Bদুটি কমিট, ব্রাঞ্চ বা ট্যাগ
git diff A...BA থেকে আলাদা হওয়ার পর B-তে যা বদলেছে

আপনি git add করলে সাধারণ git diff খালি হয়ে যায়, কারণ পরিবর্তন ইতিমধ্যে ইনডেক্সে। তখন --staged দেখুন। যেসব নতুন ফাইল কখনো যোগ হয়নি, সেগুলো diff-এ আসেই না।

diff-এর আউটপুট পড়া

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

- দিয়ে শুরু লাইন মুছে ফেলা, + দিয়ে শুরু লাইন যোগ করা, বাকিগুলো প্রসঙ্গ (প্রসঙ্গ)। @@ -10,7 +10,7 @@ মানে: অংশটি পুরনো ও নতুন উভয় সংস্করণের দশম লাইন থেকে শুরু, এবং উভয়তে সাতটি লাইন নেয়।

git diff-এর কয়েকটি কাজের ফ্ল্যাগ

git diff --stat main feature      # ফাইল অনুযায়ী সারাংশ
git diff --name-only HEAD~3       # শুধু বদলানো ফাইলের নাম
git diff --word-diff               # শব্দ ধরে তুলনা, লেখার জন্য সুবিধাজনক
git diff -w                        # স্পেসের বদল উপেক্ষা
git diff main feature -- src/      # একটি ফোল্ডারে সীমাবদ্ধ

প্রতিটি কমিটের আগে git diff --staged দেখা ভালো: এটি ডিবাগের print বা ভুলে যোগ হওয়া ফাইল ধরার শেষ সুযোগ।

git show: একটি কমিট পুরোটা

git show কমিটের মেটাডেটা এবং প্যারেন্টের তুলনায় তার diff দেখায়। আর্গুমেন্ট ছাড়া সর্বশেষ কমিট।

git show 7be41d0
git show HEAD~2 --stat           # প্যাচ ছাড়া, শুধু সারাংশ
git show v1.2.0                  # ট্যাগ: ব্যাখ্যা ও কমিট
git show main:src/config.py      # কমিটে ফাইলটি যেমন ছিল

শেষ রূপ <রিভিশন>:<পথ> বিশেষভাবে কাজের: পুরনো সংস্করণ দেখা যায়, চেকআউট না করেই। আউটপুট ফাইলে লিখলে checkout ছাড়াই মুছে যাওয়া বিষয়বস্তু ফিরে পাওয়া যায়।

git blame: এই লাইন কে বদলেছে

git blame ফাইল প্রতিটি লাইনের জন্য সর্বশেষ যে কমিট সেটি বদলেছে, তার লেখক ও তারিখ দেখায়। নামটি অভিযোগের মতো শোনায়, কিন্তু আসলে এটি প্রসঙ্গ খোঁজার সরঞ্জাম: কমিট খুঁজে বার্তা পড়ুন এবং বুঝুন কেন এমন করা হয়েছে।

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Nusrat Jahan 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Karim Ahmed 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60 — শুধু লাইনের পরিসর; -L :ফাংশনের_নাম-ও চলে।
  • -w — স্পেসের বদল উপেক্ষা, যাতে ফরম্যাটিংয়ের কমিটে আটকে না যান।
  • -C — অন্য ফাইল থেকে আসা লাইনের খোঁজ।
  • --ignore-rev <হ্যাশ> বা .git-blame-ignore-revs ফাইল — অটোফরম্যাটিংয়ের মতো বিশাল কমিট বাদ দিতে।

একটি সাধারণ তদন্ত: git blame কমিট খুঁজে দেয়, git show তাকে পুরো দেখায়, এবং ফাইলের git log পাশের বদলগুলো দেখায়।

অতীতে যাওয়া: HEAD~ ও HEAD^

কমিটকে শুধু হ্যাশ দিয়ে নয়, সম্পর্ক দিয়েও উল্লেখ করা যায়। HEAD~1 বর্তমান কমিটের প্যারেন্ট, HEAD~3 তিন ধাপ আগের। HEAD^2 merge কমিটের দ্বিতীয় প্যারেন্ট। ব্রাঞ্চ, ট্যাগ ও রিমোট ব্রাঞ্চের নামও চলে: origin/main~2। পুরো প্রকল্প পুরনো কমিটে দেখতে git switch --detach <হ্যাশ>, ফিরতে git switch -।

ভালো ও খারাপ ইতিহাস

এই কমান্ডগুলো ততটাই কাজের, যতটা ইতিহাস অর্থবহ। "fix", "wip", "আরও ঠিক" ধরনের বার্তা থাকলে git log --grep ও git blame অকেজো। ভালো কমিট একটি যৌক্তিক পরিবর্তন এবং এমন শিরোনাম, যা বলে কী ও কেন: fix: গেটওয়ের ধীরগতির জন্য API টাইমআউট ৩০ সেকেন্ড করা হলো। ছয় মাস পরে blame ঠিক এমন কমিটই খুঁজে দেবে এবং এক ঘণ্টা বাঁচাবে।

অভ্যাস: ইতিহাস ধরে বাগ খোঁজা

ধরুন, একটি রিলিজের পর API-র অনুরোধ টাইমআউটে ব্যর্থ হতে শুরু করল। কমান্ডের শৃঙ্খল দিয়ে কয়েক মিনিটে কারণে পৌঁছানো যায়।

  1. রিলিজে কী ঢুকল দেখুন: git log v1.4.0..v1.5.0 --oneline। তালিকা ছোট, তবু শিরোনাম দেখে দোষী স্পষ্ট নয়।
  2. ফাইল দিয়ে সংকীর্ণ করুন: git log v1.4.0..v1.5.0 --oneline -- src/api/। দুটি কমিট বাকি থাকে।
  3. কোডের ভেতরে খুঁজুন: git log -S "timeout" --oneline -- src/api/ সেই কমিট দেয়, যেখানে টাইমআউটের মান বদলেছে।
  4. কমিটটি পুরোটা দেখুন: git show 1c02e8f। diff-এ দেখা যায় টাইমআউট ৩০ থেকে ৫ সেকেন্ড করা হয়েছে, আর বার্তায় ব্যাখ্যা "UI-এর সাড়া দ্রুত করতে"।
  5. এই লাইনটি আর কে ছুঁয়েছে যাচাই করুন: git blame -L :build_session src/api/client.py।

এরপর সমাধান প্রকৌশলের বিষয়: মান ফিরিয়ে আনা, সেটিংসে সরানো, অথবা git revert-এ কমিট বাতিল। কমিট শত শত হলে এবং চোখে দোষী না পাওয়া গেলে সাহায্য করে git bisect, যা ইতিহাসে বাইনারি সার্চ চালিয়ে কয়েক ধাপে আচরণ ভাঙা কমিটে নিয়ে যায়।

সহজ করার কিছু সেটিং

git config --global log.date iso            # log-এর তারিখ ফরম্যাট
git config --global diff.colorMoved zebra   # diff-এ সরে যাওয়া লাইন আলাদা রঙে
git config --global core.pager "less -FRX"  # ছোট আউটপুটে পেজার না খোলা

আউটপুট স্ক্রিপ্টে প্রসেস করতে হলে রঙ ও পেজার বন্ধ করুন: git --no-pager log --format="%H %s" --no-color। মেশিন-পঠনের জন্য পূর্ণ হ্যাশ %H ব্যবহার করুন, কারণ বড় রিপোজিটরিতে সংক্ষিপ্ত প্রিফিক্স সময়ের সঙ্গে অস্পষ্ট হতে পারে।

সারসংক্ষেপ

ফিল্টারসহ git log (--oneline, --graph, --author, -S ও পথ) উত্তর দেয় "কী ঘটেছিল"। git diff তুলনা করে কাজের ফোল্ডার, ইনডেক্স ও কমিট, আর মনে রাখতে হবে ডিফল্টে সে কী তুলনা করে। git show একটি কমিট বা পুরনো ফাইলের সংস্করণ খোলে, এবং git blame কোড-লাইন থেকে সেই সিদ্ধান্তে পৌঁছে দেয়, যা লাইনটি তৈরি করেছিল। ইতিহাস পড়া ও কমিটে নেভিগেশন Git কোর্সে বাস্তব অনুশীলনে শেখানো হয়।

সাধারণ প্রশ্ন

git log থেকে কীভাবে বের হব?

q চাপুন; আউটপুট less পেজারে খোলা থাকে। পেজার ছাড়া ছাপাতে git --no-pager log বা ছোট -n সংখ্যা ব্যবহার করুন।

মুছে ফেলা একটি ফাইলের ইতিহাস কীভাবে দেখব?

git log --oneline -- পথ/ফাইল (দুটি ড্যাশসহ) চালান, এবং মোছার আগের বিষয়বস্তু পেতে git show &lt;হ্যাশ&gt;^:পথ/ফাইল।

লোকাল ব্রাঞ্চ রিমোটের সঙ্গে কীভাবে তুলনা করব?

আগে git fetch, তারপর git diff origin/main বা git log origin/main..HEAD, যাতে আপনার পাঠানো-হয়নি কমিট দেখা যায়।

ইতিহাস দেখার কোনো গ্রাফিক্যাল উপায় আছে?

হ্যাঁ, Git-এর সঙ্গে আসে gitk; এছাড়া VS Code, JetBrains IDE এবং GitHub ও GitLab-এর ওয়েব ইন্টারফেসেও কমিট গ্রাফ আছে।

git diff কিছু দেখাচ্ছে না কেন?

সম্ভবত পরিবর্তন ইতিমধ্যে git add-এ ইনডেক্সে গেছে; git diff --staged দেখুন। নতুন, ট্র্যাক না হওয়া ফাইল git diff-এ একেবারেই আসে না।

ভিডিওতে বিষয়টি শিখুন

“শূন্য থেকে আত্মবিশ্বাসী ডেভেলপার পর্যন্ত গিট” কোর্সে বিষয়টি অনুশীলনসহ বিস্তারিত শেখানো হয়েছে।

কোর্সে যান