Git هر فایل و هر کامیت را با یک اثرانگشت (هش) میشناسد. اگر حتی یک حرف پیام کامیت عوض شود، اثرانگشت عوض میشود — برای همین «ویرایش تاریخچه» در واقع ساختن کامیت جدید است، نه دستکاری فایل قدیمی.
🎯 اهداف یادگیری
- چهار نوع شیء را نام ببری: blob، tree، commit، tag
- توضیح دهی چرا بازنویسی کامیت هش را عوض میکند
- با
cat-fileوrev-parseیک کامیت را کالبدشکافی کنی - تفاوت SHA-1 و SHA-256 (مسیر Git ۳.۰) را بدانی
🧠 محتوا آدرسدهی
hash("blob " + size + "\0" + content) → شناسهٔ فایل
اگر یک بیت عوض شود، شناسه عوض میشود. دو فایل یکسان در کل تاریخچه یک blobاند — این است دلیل ارزان بودن شاخه و سریع بودن Git.
شکل ۳ — commit به tree اشاره میکند؛ tree به blobها و treeهای فرزند.
🔬 کالبدشکافی یک کامیت
git rev-parse HEAD git cat-file -p HEAD git cat-file -p 'HEAD^{tree}' # در zsh حتماً نقلقول بگذار git ls-tree -r HEAD
خروجی commit شبیه این است:
tree 4c2e9a... parent a91b77... author rezaian-dev <mrezaian.dev@gmail.com> 1757400000 +0330 committer rezaian-dev <mrezaian.dev@gmail.com> 1757400000 +0330 feat(auth): add refresh-token rotation
چهار چیز هویت کامیت را میسازند: tree، والد(ها)، هویت نویسنده/زمان، پیام. --amend روی هر کدام دست بگذارد، هش جدید است.
🏷️ annotated tag
git tag v1.0.0 # سبک: فقط یک ref git tag -a v1.0.0 -m "release" # شیء tag با امضا و پیام git cat-file -p v1.0.0
برای انتشار محصول همیشه annotated (و در فصل ۲۶ امضاشده) بساز.
🧮 SHA-1 در برابر SHA-256
| SHA-1 (میراث) | SHA-256 (آینده) | |
|---|---|---|
| طول | ۴۰ hex | ۶۴ hex |
| وضعیت ۲۰۲۶ | هنوز پیشفرض بسیاری از hostها | در Git ۲.۵۱+ برای مخزن جدید آماده |
| GitHub | پشتیبانی کامل | در حال گسترش — قبل از مهاجرت چک کن |
| آزمایش | — | git init --object-format=sha256 |
مخزن SHA-256 را نمیتوانی به ریموت SHA-1 پوش کنی. تا وقتی GitHub/تیم تو آماده نشده، روی SHA-1 بمان و فقط مفهوم را بدان.
Reftable (git init --ref-format=reftable) لایهٔ refs را سریع میکند، نه hash را. برای monorepoهای عظیم مفید است.
Git معمولاً ۷–۱۲ کاراکتر اول را میپذیرد (9f3a1c). در مخازن خیلی بزرگ ممکن است مبهم شود؛ core.abbrev را بالا ببر یا هش کامل را در اسکریپتها استفاده کن.
Junior — blob چیست؟ محتوای فایل، بدون نام. نام در tree ذخیره میشود.
Mid — چرا rename در Git «تشخیص» است نه شیء؟ چون blob همان است؛ tree فقط مسیر را عوض کرده. git log --follow این جابهجایی را حدس میزند.
Senior — commit تغییرناپذیر است یعنی چه؟ شیء در objects دیتابیس هرگز ویرایش نمیشود. «ویرایش تاریخچه» یعنی ساختن اشیای جدید و حرکت دادن اشارهگر شاخه.
✅ چکلیست فهم
- چهار نوع شیء را بلدی
cat-file -p HEADرا تفسیر میکنی- میدانی amend چرا هش را عوض میکند
- SHA-256 را با احتیاط میشناسی
فصل بعد: شاخه — ارزانترین اشاره در مهندسی نرمافزار.