پریروز در حال صحبت با طه بحث به اینجا رسید که گیت چطور تغییرات فایلها رو نگه میداره؟ من گفتم بصورت پچ فایل ذخیره میکنه و امروز رفتم داخل پوشهی `.git` که ببینم ماجرا چیه و دیدم که عمری در جهالت میزیستهام و اشتباه مینمودم. این پست حاصل جستجوی من برای یافتن جواب این سواله.
گیت فایلها رو بر اساس محتواشون ذخیره میکنه و تا زمانی که فایل تغییر نکرده، نسخهی ذخیرهشده توسط گیت ثابت میمونه.
اول کار که شما دستور `git init` رو اجرا میکنید، گیت داخل پوشهی جاری یه فولدر `.git` میسازه که محتویاتش اینه:
[meysampg@freedom git]$ git init Initialized empty Git repository in /srv/http/test/git/.git/ [meysampg@freedom git]$ ls -lah .git total 40K drwxr-xr-x 7 meysampg users 4.0K Mar 10 11:07 . drwxr-xr-x 3 meysampg users 4.0K Mar 10 11:07 .. drwxr-xr-x 2 meysampg users 4.0K Mar 10 11:07 branches -rw-r--r-- 1 meysampg users 92 Mar 10 11:07 config -rw-r--r-- 1 meysampg users 73 Mar 10 11:07 description -rw-r--r-- 1 meysampg users 23 Mar 10 11:07 HEAD drwxr-xr-x 2 meysampg users 4.0K Mar 10 11:07 hooks drwxr-xr-x 2 meysampg users 4.0K Mar 10 11:07 info drwxr-xr-x 4 meysampg users 4.0K Mar 10 11:07 objects drwxr-xr-x 4 meysampg users 4.0K Mar 10 11:07 refs
چیزی که جواب سوال بالاست در پوشهی `objects` نهفتهست.
گیت یک سیستم محتوا-آدرسیه، بدین معنی که گیت بدون توجه به نام فایل و بر اساس محتوا یک کلید منحصربفرد برای هر فایل میسازه (که همون هش SHA1ی هست که موقع کامیت کردن نشون میده) و اون رو داخل پوشهی `objects` بر اساس قاعدهی زیر ذخیره میکنه:
۱. تو یه رشته بنویس blob و بعدش فاصله و بعدش طول محتوای فایل و بعدش کاراکتر نال رو بذار (مثلا `blob 4\0`).
۲. به رشتهی بالا محتوای فایل رو بچسبون (مثلا `blob 4\0pgpg`).
۳. از رشتهی مرحلهی ۲ یه هش SHA1 بگیر و از این به بعد این میشه شناسهی این فایل (مثلا برای رشتهی بالا میشه `c8f50ec947636ea1e848da84bc6e844f593426a1`).
۴. دو کاراکتر اول رشتهی حاصل از مرحلهی ۳ رو بردار و داخل پوشهی `objects` یه پوشه بساز. با ۳۸ کاراکتر باقیمانده یه فایل داخل پوشهای که ساختی بساز (مثلا میشه `objects/c8/f50ec947636ea1e848da84bc6e844f593426a1`).
۵. با `ZLib` محتوای مرحلهی ۲ رو فشرده کن و اونو داخل فایلی که در مرحلهی ۴ ساختی ذخیره کن.
از این به بعد برای هر کاری که به اسم فایل نیازه، گیت از اون هش حاصل از مرحلهی ۳ استفاده میکنه و تا زمانی که محتوای فایل تغییر نکرده باشه، این هش ثابت میمونه.
پ.ن یک: گیت در حقیقت بیشتر از کارهایی که در بخش «جواب بلند» اومد رو برای ذخیرهسازی انجام میده ولی برای من اون قسمتش دیگه اهمیتی نداره :)). بخش Git Internals کتاب گیت کل ماجرا رو خیلی روشن و شفاف توضیح داده.