-
1. شروع به کار (getting started)
-
2. مقدمات گیت (git basics chapter)
- 2.1 گرفتن یک مخزن گیت (Getting a Git Repository)
- 2.2 ثبت تغییرات در مخزن (Recording Changes to the Repository)
- 2.3 مشاهده تاریخچه کامیتها (Viewing the Commit History)
- 2.4 بازگرداندن تغییرات (Undoing Things)
- 2.5 کار کردن با ریموت ها (Working with Remotes)
- 2.6 تگ کردن (Tagging)
- 2.7 نام مستعار گیت (Git Aliases)
- 2.8 خلاصه (summary)
-
3. انشعابگیری در گیت (Git Branching)
-
4. گیت روی سرور (Git on the server)
- 4.1 پروتکلها (The Protocols)
- 4.2 راهاندازی گیت روی یک سرور (Getting Git on a Server)
- 4.3 ایجاد کلید عمومی SSH شما (Generating Your SSH Public Key)
- 4.4 نصب و راهاندازی سرور (Setting up server)
- 4.5 سرویسدهنده گیت (Git Daemon)
- 4.6 HTTP هوشمند (Smart HTTP)
- 4.7 گیتوب (GitWeb)
- 4.8 گیتلب (GitLab)
- 4.9 گزینههای میزبانی شخص ثالث (Third Party Hosted Options)
- 4.10 خلاصه (Summary)
-
5. گیت توزیعشده (Distributed git)
-
6. GitHub (گیت هاب)
-
7. ابزارهای گیت (Git Tools)
- 7.1 انتخاب بازبینی (Revision Selection)
- 7.2 مرحلهبندی تعاملی (Interactive Staging)
- 7.3 ذخیره موقت و پاکسازی (Stashing and Cleaning)
- 7.4 Signing Your Work (امضای کارهای شما)
- 7.5 جستجو (Searching)
- 7.6 بازنویسی تاریخچه (Rewriting History)
- 7.7 بازنشانی به زبان ساده (Reset Demystified)
- 7.8 ادغام پیشرفته (Advanced Merging)
- 7.9 بازاستفاده خودکار از حل تضادها (Rerere)
- 7.10 اشکالزدایی با گیت (Debugging with Git)
- 7.11 سابماژول ها (Submodules)
- 7.12 بستهبندی (Bundling)
- 7.13 جایگزینی (Replace)
- 7.14 ذخیرهسازی اطلاعات ورود (Credential Storage)
- 7.15 خلاصه (Summary)
-
8. سفارشیسازی Git (Customizing Git)
-
9. گیت و سیستمهای دیگر (Git and Other Systems)
-
10. (Git Internals)
- 10.1 ابزارها و دستورات سطح پایین (Plumbing and Porcelain)
- 10.2 اشیا گیت (Git Objects)
- 10.3 مراجع گیت (Git References)
- 10.4 فایلهای بسته (Packfiles)
- 10.5 نگاشت (The Refspec)
- 10.6 پروتکلهای انتقال (Transfer Protocols)
- 10.7 نگهداری و بازیابی دادهها (Maintenance and Data Recovery)
- 10.8 متغیرهای محیطی (Environment Variables)
- 10.9 (Summary)
-
A1. پیوست A: گیت در محیطهای دیگر (Git in Other Environments)
- A1.1 رابط های گرافیکی (Graphical Interfaces)
- A1.2 Git در ویژوال استودیو (Git in Visual Studio)
- A1.3 Git در Visual Studio Code (Git in Visual Studio Code)
- A1.4 Git در IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine (Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine)
- A1.5 Git در Sublime Text (Git in Sublime Text)
- A1.6 گیت در بش (Git in Bash)
- A1.7 Git در Zsh (Git in Zsh)
- A1.8 Git در PowerShell (Git in PowerShell)
- A1.9 خلاصه (Summary)
-
A2. پیوست B: گنجاندن گیت در برنامههای شما (Embedding Git in your Applications)
-
A3. پیوست C: دستورات گیت (Git Commands)
- A3.1 تنظیم و پیکربندی (Setup and Config)
- A3.2 گرفتن و ایجاد پروژهها (Getting and Creating Projects)
- A3.3 نمونهبرداری پایهای (Basic Snapshotting)
- A3.4 انشعابگیری و ادغام (Branching and Merging)
- A3.5 بهاشتراکگذاری و بهروزرسانی پروژهها (Sharing and Updating Projects)
- A3.6 بازرسی و مقایسه (Inspection and Comparison)
- A3.7 عیبیابی (Debugging)
- A3.8 اعمال تغییرات به صورت پچ (Patching)
- A3.9 ایمیل (Email)
- A3.10 سیستمهای خارجی (External Systems)
- A3.11 مدیریت (Administration)
- A3.12 دستورات سطح پایین گیت (Plumbing Commands)
10.6 (Git Internals) - پروتکلهای انتقال (Transfer Protocols)
پروتکلهای انتقال (Transfer Protocols)
Git میتواند دادهها را بین دو repository به دو روش اصلی منتقل کند: پروتکل “dumb” و پروتکل “smart”. این بخش بهطور سریع توضیح میدهد که این دو پروتکل اصلی چطور عمل میکنند.
پروتکل ساده (The Dumb Protocol)
اگر میخواهید یک repository را فقط به صورت read-only از طریق HTTP سرو کنید، به احتمال زیاد از پروتکل dumb استفاده میشود. به این پروتکل “dumb” گفته میشود چون در سمت سرور هیچ کد اختصاصی مربوط به Git در طول فرآیند انتقال نیاز ندارد؛ فرآیند fetch مجموعهای از درخواستهای HTTP GET است که در آن کلاینت میتواند ساختار repository روی سرور را فرض بگیرد.
یادداشت
|
این پروتکل امروزه بسیار بهندرت استفاده میشود. ایمنسازی یا خصوصیسازی آن سخت است، به همین دلیل بیشتر میزبانهای Git (چه ابری و چه on-premises) استفاده از آن را رد میکنند. بهطور کلی توصیه میشود از پروتکل smart استفاده کنید که کمی جلوتر توضیح داده میشود. |
بیایید فرآیند http-fetch
برای کتابخانه simplegit را دنبال کنیم:
$ git clone http://server/simplegit-progit.git
اولین کاری که این دستور انجام میدهد، دریافت فایل info/refs
است.
این فایل توسط دستور update-server-info
نوشته میشود، به همین دلیل باید آن را بهعنوان یک post-receive hook فعال کنید تا انتقال HTTP بهدرستی کار کند:
=> GET info/refs
ca82a6dff817ec66f44342007202690a93763949 refs/heads/master
حالا لیستی از remote references و مقادیر SHA-1 دارید. سپس بررسی میکنید که HEAD reference چیست تا بدانید در پایان باید چه چیزی را checkout کنید:
=> GET HEAD
ref: refs/heads/master
در اینجا باید پس از پایان فرآیند، branch master
را checkout کنید.
اکنون آماده شروع فرآیند walking هستید.
از آنجا که نقطه شروع شما همان commit object ca82a6
است که در فایل info/refs
دیدید، کار را با دریافت آن آغاز میکنید:
=> GET objects/ca/82a6dff817ec66f44342007202690a93763949
(179 bytes of binary data)
یک object دریافت میکنید – این object روی سرور به صورت loose format است و شما آن را از طریق یک درخواست ساده HTTP GET گرفتهاید. میتوانید آن را با zlib از حالت فشرده خارج کنید، header را جدا کنید و محتوای commit را ببینید:
$ git cat-file -p ca82a6dff817ec66f44342007202690a93763949
tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
Change version number
سپس باید دو object دیگر دریافت کنید: cfda3b
که tree of content مربوط به commit است، و 085bb3
که parent commit است:
=> GET objects/08/5bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
(179 bytes of data)
اینجا commit object بعدی را دارید. حالا tree object را بگیرید:
=> GET objects/cf/da3bf379e4f8dba8717dee55aab78aef7f4daf
(404 - Not Found)
اوه – بهنظر میرسد این tree object روی سرور به صورت loose format نیست، بنابراین پاسخ 404 دریافت میکنید. دلایل احتمالی این موضوع: object ممکن است در یک alternate repository باشد یا در یک packfile در همین مخزن. Git ابتدا وجود هر alternate را بررسی میکند:
=> GET objects/info/http-alternates
(empty file)
اگر لیستی از آدرسهای alternate برگردانده شود، Git در آنها به دنبال loose files و packfiles میگردد – این مکانیزم خوبی برای پروژههایی است که fork یکدیگر هستند تا روی دیسک objects را بهاشتراک بگذارند.
اما چون اینجا هیچ alternateای لیست نشده، object شما باید در یک packfile باشد.
برای دیدن اینکه چه packfiles روی سرور موجود است، باید فایل objects/info/packs
را بگیرید که لیستی از آنها را دارد (این هم توسط update-server-info
تولید میشود):
=> GET objects/info/packs
P pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
روی سرور فقط یک packfile وجود دارد، پس مشخص است object شما داخل آن است، اما باید index file را بررسی کنید تا مطمئن شوید. این بررسی همچنین زمانی مفید است که چندین packfile روی سرور وجود داشته باشد تا بفهمید کدام یک شامل object موردنظر شما است:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.idx
(4k of binary data)
حالا که packfile index را دارید، میتوانید ببینید که آیا object شما در آن وجود دارد یا نه – چون این index لیست SHA-1s مربوط به objects موجود در packfile و آدرسهای آنها را دارد. چون object شما در آن وجود دارد، کل packfile را دریافت کنید:
=> GET objects/pack/pack-816a9b2334da9953e530f27bcac22082a9f5b835.pack
(13k of binary data)
حالا tree object را دارید، پس ادامه میدهید و commits خود را پیمایش میکنید.
همه آنها نیز داخل همان packfile هستند، بنابراین نیازی به درخواستهای بیشتر به سرور نیست.
Git یک working copy از branch master
که در ابتدای کار توسط HEAD reference مشخص شد، checkout میکند.
پروتکل هوشمند (The Smart Protocol)
پروتکل dumb ساده است اما کمی ناکارآمد بوده و نمیتواند دادهای از کلاینت به سرور بنویسد. پروتکل smart روشی رایجتر برای انتقال داده است، اما نیاز به پردازشی در سمت ریموت دارد که از Git آگاه باشد – بتواند دادههای محلی را بخواند، بفهمد کلاینت چه دارد و چه نیاز دارد، و یک packfile سفارشی برای آن تولید کند. دو مجموعه فرآیند برای انتقال داده وجود دارد: یک جفت برای uploading data و یک جفت برای downloading data.
بارگذاری داده (Uploading Data)
برای upload data به یک فرآیند ریموت، Git از فرآیندهای send-pack
و receive-pack
استفاده میکند.
فرآیند send-pack
روی کلاینت اجرا شده و به فرآیند receive-pack
در سمت ریموت متصل میشود.
پروتکل امن شل SSH (SSH)
برای مثال، اگر شما در پروژهتان دستور git push origin master
را اجرا کنید و origin
یک آدرس با پروتکل SSH باشد، Git فرآیند send-pack
را اجرا کرده و یک اتصال SSH به سرور برقرار میکند.
سپس سعی میکند دستوری روی سرور ریموت اجرا کند که شبیه به این است:
$ ssh -x git@server "git-receive-pack 'simplegit-progit.git'"
00a5ca82a6dff817ec66f4437202690a93763949 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1+github-607-gfba4028 delete-refs
0000
دستور git-receive-pack
بلافاصله یک خط برای هر reference موجود برمیگرداند – در این مثال فقط branch master
و مقدار SHA-1 آن.
اولین خط همچنین شامل لیستی از قابلیتهای سرور است (اینجا: report-status
, delete-refs
و چند مورد دیگر از جمله شناسه کلاینت).
دادهها به صورت chunks منتقل میشوند. هر chunk با یک مقدار ۴ کاراکتری هگزادسیمال شروع میشود که طول chunk (شامل همان ۴ بایت اول) را مشخص میکند. معمولاً هر chunk شامل یک خط داده و یک linefeed پایانی است. اولین chunk شما با 00a5 شروع میشود که در مبنای هگز برابر با 165 است، یعنی طول chunk برابر 165 بایت است. chunk بعدی 0000 است، یعنی سرور لیست references خود را تمام کرده.
حالا که وضعیت سرور مشخص شد، فرآیند send-pack
تعیین میکند چه commitsای دارد که سرور ندارد.
برای هر reference که این push قرار است بهروزرسانی کند، فرآیند send-pack
آن اطلاعات را به receive-pack
میفرستد.
برای مثال، اگر شما در حال بهروزرسانی branch master
و اضافهکردن branch experiment
باشید، پاسخ send-pack
چیزی شبیه به این خواهد بود:
0076ca82a6dff817ec66f44342007202690a93763949 15027957951b64cf874c3557a0f3547bd83b3ff6 \
refs/heads/master report-status
006c0000000000000000000000000000000000000000 cdfdb42577e2506715f8cfeacdbabc092bf63e8d \
refs/heads/experiment
0000
Git برای هر reference که بهروزرسانی میکنید یک خط میفرستد که شامل طول خط، old SHA-1، new SHA-1 و reference در حال بهروزرسانی است.
اولین خط همچنین قابلیتهای کلاینت را دارد.
مقدار SHA-1 پر از صفر (0000…
) یعنی قبلاً چیزی وجود نداشته – چون دارید یک reference جدید (experiment
) اضافه میکنید.
اگر در حال حذف یک reference باشید، حالت برعکس خواهد بود: سمت راست پر از صفر خواهد بود.
در مرحله بعد، کلاینت یک packfile شامل تمام objectsی که سرور ندارد ارسال میکند. در نهایت، سرور با یک پیام موفقیت (یا شکست) پاسخ میدهد:
000eunpack ok
پروتکل انتقال ابرمتن امن HTTPS (HTTP(S))
این فرآیند روی HTTP تقریباً مشابه است، فقط handshaking کمی متفاوت است. اتصال با این درخواست شروع میشود:
=> GET http://server/simplegit-progit.git/info/refs?service=git-receive-pack
001f# service=git-receive-pack
00ab6c5f0e45abd7832bf23074a333f739977c9e8188 refs/heads/master□report-status \
delete-refs side-band-64k quiet ofs-delta \
agent=git/2:2.1.1~vmg-bitmaps-bugaloo-608-g116744e
0000
این پایان اولین تبادل client-server است.
سپس کلاینت یک درخواست دیگر میفرستد، این بار یک POST، با دادهای که توسط send-pack
تولید شده:
=> POST http://server/simplegit-progit.git/git-receive-pack
درخواست POST شامل خروجی send-pack
و packfile بهعنوان payload است.
سرور در پاسخ، موفقیت یا شکست عملیات را مشخص میکند.
به خاطر داشته باشید که پروتکل HTTP ممکن است این دادهها را در قالب chunked transfer encoding نیز بستهبندی کند.
دانلود داده (Downloading Data)
وقتی داده دریافت میکنید، فرآیندهای fetch-pack
و upload-pack
درگیر هستند.
کلاینت فرآیند fetch-pack
را اجرا میکند که به فرآیند upload-pack
روی سمت ریموت متصل میشود تا مذاکره کند چه دادهای باید منتقل شود.
پروتکل امن شل SSH (SSH)
اگر fetch را از طریق SSH انجام دهید، fetch-pack
چیزی شبیه این اجرا میکند:
$ ssh -x git@server "git-upload-pack 'simplegit-progit.git'"
پس از اتصال fetch-pack
، فرآیند upload-pack
چیزی شبیه این برمیگرداند:
00dfca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fe2409a098dc3e53539a9028a94b6224db9d6a6b6 refs/heads/master
0000
این بسیار شبیه پاسخی است که receive-pack
میدهد، اما قابلیتها متفاوت هستند.
علاوه بر این، مشخص میکند که HEAD به چه چیزی اشاره میکند (symref=HEAD:refs/heads/master
) تا کلاینت بداند اگر این یک clone باشد، باید چه چیزی را checkout کند.
در این مرحله، فرآیند fetch-pack
بررسی میکند چه objectsای دارد و با ارسال “want” همراه با مقدار SHA-1، اعلام میکند که چه چیزی میخواهد.
سپس با ارسال “have” همراه با مقادیر SHA-1، مشخص میکند چه چیزی را دارد.
در پایان این لیست، با نوشتن “done” فرآیند upload-pack
را شروع میکند تا packfile دادههای موردنیاز ارسال شود:
003cwant ca82a6dff817ec66f44342007202690a93763949 ofs-delta
0032have 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
0009done
0000
پروتکل انتقال ابرمتن امن (HTTP(S))
handshake در عملیات fetch شامل دو درخواست HTTP است.
اولی یک GET
به همان endpointی است که در پروتکل dumb استفاده میشود:
=> GET $GIT_URL/info/refs?service=git-upload-pack
001e# service=git-upload-pack
00e7ca82a6dff817ec66f44342007202690a93763949 HEAD□multi_ack thin-pack \
side-band side-band-64k ofs-delta shallow no-progress include-tag \
multi_ack_detailed no-done symref=HEAD:refs/heads/master \
agent=git/2:2.1.1+github-607-gfba4028
003fca82a6dff817ec66f44342007202690a93763949 refs/heads/master
0000
این بسیار شبیه اجرای git-upload-pack
از طریق SSH است، اما تبادل دوم بهعنوان یک درخواست جداگانه انجام میشود:
=> POST $GIT_URL/git-upload-pack HTTP/1.0
0032want 0a53e9ddeaddad63ad106860237bbf53411d11a7
0032have 441b40d833fdfa93eb2908e52742248faf0ee993
0000
باز هم فرمت همان قبلی است. پاسخ این درخواست موفقیت یا شکست را مشخص میکند و شامل packfile است.
خلاصه پروتکلها (Protocols Summary)
این بخش یک مرور بسیار ابتدایی از پروتکلهای انتقال داده بود.
پروتکل ویژگیهای بسیار بیشتری دارد، مثل قابلیتهای multi_ack
یا side-band
، اما توضیح آنها خارج از محدوده این کتاب است.
ما سعی کردیم حسی کلی از تعاملات بین کلاینت و سرور به شما بدهیم؛ اگر به دانشی بیشتر از این نیاز دارید، احتمالاً باید به Git source code مراجعه کنید.