گیت و عملکرد داخلی آن

گیت و عملکرد داخلی آن
این پست مقدمه ای در مورد عملکرد داخلی GIT است. در اینجا ما بهتر خواهیم فهمید که اجرای آن چگونه کار می کند و دستورات اساسی که در زندگی روزمره استفاده می کنیم.
توصیه من این است که هنگام خواندن شما آنچه را که در اینجا منتقل می شود تمرین کنید.
امیدوارم از آن لذت ببرید خواندن خوب!
لوله کشی کماندوس و چینی
دستورات GIT به دو دسته تقسیم می شوند: لوله کشی و چینی. لوله کشی به دستورات سطح پایین و پرسلن دستورات سطح بالاتری اشاره دارد. دستورات چینی برای ما شناخته شده است: add
با commit
با clone
، و غیره دستورات لوله کشی در زیر هود Git قرار دارند و معمولاً به صورت دستی مورد استفاده قرار نمی گیرند. با وجود این GIT با استفاده از دستورات چینی ، از دستورات لوله کشی استفاده فشرده می کند.
فهرست راهنما .git
بیایید با ابتدای همه چیز شروع کنیم. هنگامی که ما یک مخزن GIT جدید را با git init
، git یک دایرکتوری ایجاد می کند .git
با دایرکتوری ها و پرونده های زیر:
$ ls -F1 .git
config
description
HEAD
hooks/
info/
objects/
refs/
Aquivo description
توسط GitWeb استفاده می شود. Aquivo config
شامل تنظیمات خاص پروژه است. دایرکتوری info
حاوی الگوهای جهانی است که نادیده گرفته می شوند و توسط آن ردیابی نمی شوند .gitignore
بشر دایرکتوری hooks
اسکریپت های قلاب Contém.
حال بیایید به آنچه در این مقاله علاقه مند است ، برسیم. دایرکتوری objects
این جایی است که تمام محتوایی که توسط GIT مدیریت می شوند ذخیره می شوند. دایرکتوری refs
فروشگاه ها را به تعهدات (شاخه ها) ارجاع می دهد. سرانجام ، خاص HEAD
این به شاخه فعلی است که برای تعهدات استفاده می شود. بیایید به طور مفصل ببینیم که چگونه GIT هر یک از این بخش ها را در داخل کار می کند.
git add
اشمیه git commit
بیایید ببینیم چه اتفاقی می افتد وقتی که ما معمولاً با استفاده از دستورات چینی مانند git add
اشمیه git commit
:
$ echo "Hello, world!" > hello.txt
$ git add hello.txt
$ git commit -m "add hello.txt"
به یاد داشته باشید که من گفتم که تمام محتوای مدیریت شده توسط GIT در آن ذخیره می شود .git/object
؟ بنابراین بیایید به آنچه در داخل بعد از تعهد ایجاد شده است نگاه کنیم:
$ find .git/objects/
...
.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b -- blob
.git/objects/ec/947e3dd7a7752d078f1ed0cfde7457b21fef58 -- tree
.git/objects/c6/2126fdb09e19fec4e71e0d9a4351784dab680e -- commit
توجه داشته باشید که پس از تعهد ، سه دایرکتوری ایجاد شد. هر دایرکتوری یک شیء GIT را نشان می دهد ، که در این حالت عبارتند از: حباب ، درخت و تعهد.
ذخیره اشیاء
قبل از ادامه ، درک این موضوع که چگونه GIT اشیاء خود را ذخیره می کند ، مهم است. همانطور که قبلاً گفته شد همه چیز در آن ذخیره شده است .git/objects/
و برای انجام این کار ، GIT از توابع هش استفاده می کند.
توابع هش داده شده با داده های اندازه پویا برای مقادیر اندازه ثابت نقشه برداری شده است. پیاده سازی های بد می توانند به راحتی منجر به برخورد شوند ، جایی که می توان دو داده با اندازه متفاوت را به همان هش نقشه برداری کرد.
هنگامی که ما قبلاً تعهد ایجاد کردیم ، دیدیم که سه شیء تولید شده است و همه با استفاده از یک عملکرد هش ایجاد شده اند. این به معنای نام های گسترده ای مانند مثلاً است 065c57718c8acfe576b5ea5358cf3a8f461c69e2
بشر نام الگوریتم مورد استفاده GIT SHA-1 است. همچنین ، همانطور که محتوای اصلی هش نمی تواند بخواند ، از آن به عنوان کلید الگوریتم تراکم ZLIB استفاده می شود. این بدان معنی است که می توانیم بگوییم که GIT یک پایگاه داده با ارزش کلیدی است!
آخرین اطلاعات مهم این است که اگر محتوا یکسان باشد ، اما نه ، اشیاء حباب با همان هش تولید می شوند. این امر به این دلیل است که یک تعهد اطلاعات دیگری را برای ایجاد هش در نظر می گیرد.
شیء حباب
شیء Blob نشان دهنده هر محتوا است. در این حالت و رایج ترین مورد ، محتوای یک پرونده را نشان می دهد. برای ایجاد این شی از دستور لوله کشی استفاده خواهیم کرد git hash-object
:
$ echo "Hello, Git!" > hello.txt
$ git hash-object -w hello.txt
670a245535fe6316eb2316c1103b1a88bb519334
در اینجا اولین شیء است که توسط Git ایجاد شده است. توجه داشته باشید که این همان نوع شیئی است که قبلاً ایجاد شده بود که ما به روشی مشترک متعهد شدیم. گزینه -w
نشان می دهد که git برای ذخیره این شیء در .git/objects
بشر ای hello.txt
این نام پرونده است:
$ find .git/objects/
...
.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b -- blob
.git/objects/ec/947e3dd7a7752d078f1ed0cfde7457b21fef58 -- tree
.git/objects/c6/2126fdb09e19fec4e71e0d9a4351784dab680e -- commit
.git/objects/67/0a245535fe6316eb2316c1103b1a88bb519334 -- blob (novo)
یک دستور GIT وجود دارد که در آن می توانیم ببینیم محتوای اصلی هر شیء GIT چیست ، یعنی git cat-file
:
$ git cat-file -p 670a245535fe6316eb2316c1103b1a88bb519334
Hello, Git!
قبل از رفتن به موضوع بعدی ، ما بهتر است هش ایجاد شده توسط GIT را تجزیه و تحلیل کنیم. همانطور که توضیح داده شد GIT از SHA-1 برای ایجاد هش استفاده می کند. آیا می توانیم از یک الگوریتم SHA-1 یک هش معتبر ایجاد کنیم؟ پاسخ این است: بله!:
$ echo -e "Hello, Git!" | openssl sha1
e40153b3e43a5ed7fa00ce6bd7a576763b88dab2
اما … مدتی صبر کنید ، همان هش نبود که توسط Git ایجاد شده است! چه اتفاقی افتاد؟ علاوه بر GIT ، محتوا را بر اساس محتوا ایجاد کنید ، اطلاعات مهمی را قبل از محتوای اصلی اضافه می کند. این محتوا از استاندارد پیروی می کند object-type {content-size}\0
بشر بیایید این را در ابتدای محتوا اضافه کنیم و ببینیم آیا هش مساوی ایجاد می شود:
$ echo -e "blob 12\0Hello, Git!" | openssl sha1
670a245535fe6316eb2316c1103b1a88bb519334
حالا بله ، یک هش معتبر!
موضوع درخت
شیء درخت نمایانگر اشیاء مختلف حباب و/یا درختان دیگر است. این محتوای پرونده را ضبط می کند و اطلاعات بیشتری در مورد اشیاء Blob اضافه می کند. برای این شی دو دستور وجود دارد: git update-index
اشمیه git write-tree
:
فرمان git update-index
اطلاعات مربوط به حافظه پنهان را اضافه کنید. در مورد ، 100644
این یک حق معمولی را نشان می دهد و همچنین نامی را به شیء حباب اضافه می کند که در این شیء درخت جدید درج شده است ، که معمولاً به پرونده ای که محتوا در آن است اشاره دارد.
$ git update-index --add --cacheinfo 100644 670a245535fe6316eb2316c1103b1a88bb519334 hello.txt
در آخر ، بیایید دستور را اجرا کنیم git write-tree
که در واقع یک درخت شی جدید ایجاد می کند. در این مرحله می توانیم قبل از اجرای آن ، چند اشیاء حباب را که می خواهیم اضافه کنیم git write-tree
:
$ git write-tree
d3ec8a0f5950fb1f73ce0d1ed55cd6fa7afcdeb9
آماده اکنون ما یک شی دیگر ایجاد کرده ایم! ما می توانیم وارد شویم .git/objects/
این یک شیء دیگر ایجاد شده است:
$ find .git/objects/
...
.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b -- blob
.git/objects/ec/947e3dd7a7752d078f1ed0cfde7457b21fef58 -- tree
.git/objects/c6/2126fdb09e19fec4e71e0d9a4351784dab680e -- commit
.git/objects/67/0a245535fe6316eb2316c1103b1a88bb519334 -- blob (novo)
.git/objects/d3/ec8a0f5950fb1f73ce0d1ed55cd6fa7afcdeb9 -- tree (novo)
اتهامات
این شیء یک تعهد را نشان می دهد ، این اطلاعات مفیدی است که برای شناسایی تغییراتی که ایجاد شده است استفاده می شود. برای این شی از دستور استفاده خواهیم کرد git commit-tree
، آن را به عنوان یک پارامتر یک شیء درخت ، تعهد قبلی و پیام توصیف تعهد دریافت می کند:
$ git commit-tree d3ec8a0f5950fb1f73ce0d1ed55cd6fa7afcdeb9 -p bdacb9cd59348d39994e4cb392b734f9236bd859 -m "update hello.txt"
ما باید از پارامتر آگاه باشیم -p
که نشان دهنده تعهد قبلی است. این باید به عنوان تاریخچه تعهد با تعهد به تعهد قبلی مراجعه شود.
$ find .git/objects/
...
.git/objects/af/5626b4a114abcb82d63db7c8082c3c4756e51b -- blob
.git/objects/ec/947e3dd7a7752d078f1ed0cfde7457b21fef58 -- tree
.git/objects/bd/acb9cd59348d39994e4cb392b734f9236bd859 -- commit
.git/objects/67/0a245535fe6316eb2316c1103b1a88bb519334 -- blob (novo)
.git/objects/d3/ec8a0f5950fb1f73ce0d1ed55cd6fa7afcdeb9 -- tree (novo)
.git/objects/12/7f0bcadb277747bfa75cc14014c91941d26d94 -- commit (novo)
بله ، این یک شیء تعهد معتبر و همچنین موردی است که توسط git commit
بشر حال ، اگر ما اجرا کنیم git log
، ما چیز جالبی خواهیم دید:
$ git log
commit c62126fdb09e19fec4e71e0d9a4351784dab680e (HEAD -> main)
Author: Lucas
Date: Wed Mar 12 10:26:28 2025 -0300
add hello.txt
دلیل فقط اولین تعهد ایجاد شده چیست؟ ساده: Refs! توجه داشته باشید که اولین تعهد به شعبه اشاره دارد main
و در آخرین تعهد ما ساخته شده است ، به هیچ وجه هیچ اشاره ای به شعبه اضافه نمی کنیم main
بشر
منابع
از منابع استفاده می شود به گونه ای که چندین تعهد به همان زمینه اشاره دارد. برای افزودن مرجع ما main
ما می توانیم از دستور استفاده کنیم git update-ref
:
$ git update-ref refs/heads/main 127f0bcadb277747bfa75cc14014c91941d26d94
حالا ، بیایید اجرا کنیم git log
برای دیدن رفتار خود:
$ git log
commit 127f0bcadb277747bfa75cc14014c91941d26d94 (HEAD -> main)
Author: Lucas
Date: Wed Mar 12 10:34:20 2025 -0300
update hello.txt
commit c62126fdb09e19fec4e71e0d9a4351784dab680e
Author: Lucas
Date: Wed Mar 12 10:26:28 2025 -0300
add hello.txt
به زودی ، ما یک شاخه هستیم main
با اشاره به آخرین تعهد ساخته شده. به آن شاخه توجه داشته باشید main
این فقط به آخرین تعهد ساخته شده اشاره دارد ، او به تعهدات قبلی اشاره نمی کند. به همین دلیل مهم و اساسی است که وقتی ما یک تعهد ایجاد می کنیم ، باید مرجع را به تعهد قبلی منتقل کنیم.
برای نشان دادن بهتر این عمل ، می توانیم با git cat-file
که متعهد 127f0bcadb277747bfa75cc14014c91941d26d94
زمینه ای به نام دارد parent
مراجعه به تعهد قبلی:
$ git cat-file -p 127f0bcadb277747bfa75cc14014c91941d26d94
tree d3ec8a0f5950fb1f73ce0d1ed55cd6fa7afcdeb9
parent c62126fdb09e19fec4e71e0d9a4351784dab680e
author Lucas 1741786460 -0300
committer Lucas 1741786460 -0300
update hello.txt
پایان
شرط می بندم که من هیچ ایده ای نداشتم که عملکرد داخلی GIT چقدر جالب باشد ، درست است؟ اما این همه چیز نیست! هنوز مطالب وجود دارد که در این مقاله به آن پرداخته نشده است ، مانند RefSpec ، پروتکل های انتقال ، متغیرهای محیط و موارد دیگر …
پس از اتمام این خواندن ، من اکیداً توصیه می کنم که به دنبال کتاب رایگان در وب سایت رسمی GIT به نام Pro Git باشید که در آن عملیات GIT از سطح اساسی به پیشرفته ترین آنها پرداخته می شود. برای این مقاله از پایه ای از فصل استفاده کردم: 10. Git Internalals
امیدوارم از آن لذت برده باشید و امیدوارم که این مقاله نمای گسترده تری از Git ارائه داده باشد. این به عنوان یک توصیه و ایده پروژه است ، و اجرای ساده GIT را به زبان مورد علاقه خود انجام می دهد.
مرا در شبکه های من دنبال کنید: X ، LinkedIn و GitHub.