میثم پورگنجی
میثم پورگنجی
خواندن ۲ دقیقه·۷ سال پیش

گیت چطور فایل‌ها رو ذخیره می‌کنه؟

پریروز در حال صحبت با طه بحث به اینجا رسید که گیت چطور تغییرات فایل‌ها رو نگه می‌داره؟ من گفتم بصورت پچ فایل ذخیره می‌کنه و امروز رفتم داخل پوشه‌ی `.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 کتاب گیت کل ماجرا رو خیلی روشن و شفاف توضیح داده.

git
مهندسی داده، برنامه‌نویسی و ریاضی
شاید از این پست‌ها خوشتان بیاید