-
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)
7.13 ابزارهای گیت (Git Tools) - جایگزینی (Replace)
جایگزینی (Replace)
دستور replace
به شما اجازه میدهد یک شیء در گیت مشخص کنید و بگویید «هر بار که به این شیء ارجاع داده میشود، تظاهر کن که این شیء، شیء دیگری است».
این بیشتر برای جایگزینی یک کامیت در تاریخچه شما با کامیت دیگری مفید است بدون اینکه مجبور باشید کل تاریخچه را مثلاً با git filter-branch
بازسازی کنید.
برای مثال، فرض کنید تاریخچه کد بسیار بزرگی دارید و میخواهید مخزن خود را به دو بخش تقسیم کنید: یک تاریخچه کوتاه برای توسعهدهندگان جدید و یک تاریخچه بسیار طولانی و بزرگتر برای کسانی که به دادهکاوی علاقهمندند. میتوانید یک تاریخچه را روی دیگری پیوند بزنید، به این صورت که اولین کامیت در خط جدید را با آخرین کامیت در خط قدیمی «جایگزین» کنید. این کار خوب است چون به این معنی است که در واقع نیازی نیست هر کامیت در تاریخچه جدید را بازنویسی کنید، همانطور که معمولاً برای پیوستن آنها به هم باید انجام میدادید (زیرا والد بودن روی SHA-1 ها تأثیر میگذارد).
بیایید این را امتحان کنیم.
یک مخزن موجود را میگیریم، آن را به دو مخزن تقسیم میکنیم، یکی جدید و یکی تاریخی، و سپس میبینیم چگونه میتوانیم آنها را بدون تغییر مقادیر SHA-1 مخزن جدید از طریق replace
دوباره ترکیب کنیم.
ما از یک مخزن ساده با پنج کامیت ساده استفاده خواهیم کرد:
$ git log --oneline
ef989d8 Fifth commit
c6e1e95 Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
ما میخواهیم این را به دو شاخه تاریخچه تقسیم کنیم. یک شاخه از کامیت اول تا کامیت چهارم است — که تاریخچه تاریخی خواهد بود. شاخه دوم فقط کامیتهای چهارم و پنجم خواهد بود — که تاریخچه جدید است.

خب، ساختن تاریخچه تاریخی آسان است، میتوانیم یک شاخه در تاریخچه ایجاد کنیم و سپس آن شاخه را به شاخه master
یک مخزن راه دور جدید push کنیم.
$ git branch history c6e1e95
$ git log --oneline --decorate
ef989d8 (HEAD, master) Fifth commit
c6e1e95 (history) Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit

history
branchحالا میتوانیم شاخه جدید history
را به شاخه master
مخزن جدید خود push کنیم:
$ git remote add project-history https://github.com/schacon/project-history
$ git push project-history history:master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (12/12), 907 bytes, done.
Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
To git@github.com:schacon/project-history.git
* [new branch] history -> master
خوب، پس تاریخچه ما منتشر شده است. حال بخش سختتر، کوتاه کردن تاریخچه جدیدمان است تا کوچکتر شود. ما نیاز به همپوشانی داریم تا بتوانیم یک کامیت را در یکی با کامیت معادل در دیگری جایگزین کنیم، بنابراین این تاریخچه را فقط به کامیتهای چهارم و پنجم محدود میکنیم (پس کامیت چهارم همپوشانی دارد).
$ git log --oneline --decorate
ef989d8 (HEAD, master) Fifth commit
c6e1e95 (history) Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
در این حالت مفید است که یک کامیت پایه ایجاد کنیم که دستورالعملهایی درباره چگونگی گسترش تاریخچه دارد، تا توسعهدهندگان دیگر بدانند اگر به اولین کامیت در تاریخچه کوتاه شده برخورد کردند و به تاریخچه بیشتری نیاز داشتند، چه کار کنند. پس کاری که میکنیم این است که یک شیء کامیت اولیه به عنوان نقطه پایه با دستورالعملها ایجاد کنیم، سپس کامیتهای باقیمانده (چهارم و پنجم) را روی آن ریبیس کنیم.
برای این کار، باید نقطهای برای تقسیم انتخاب کنیم، که برای ما کامیت سوم است، که در زبان SHA برابر با 9c68fdc
است.
پس کامیت پایه ما بر اساس آن درخت خواهد بود.
میتوانیم کامیت پایه خود را با استفاده از دستور commit-tree
ایجاد کنیم، که فقط یک درخت را میگیرد و یک شیء کامیت جدید بدون والد با SHA-1 جدید به ما میدهد.
$ echo 'Get history from blah blah blah' | git commit-tree 9c68fdc^{tree}
622e88e9cbfbacfb75b5279245b9fb38dfea10cf
یادداشت
|
دستور |

commit-tree
خوب، حالا که یک کامیت پایه داریم، میتوانیم بقیه تاریخچه خود را با git rebase --onto
روی آن قرار دهیم.
آرگومان --onto
همان SHA-1 است که از commit-tree
گرفتیم و نقطه ریبیس همان کامیت سوم (والد اولین کامیتی که میخواهیم نگه داریم، یعنی 9c68fdc
) خواهد بود:
$ git rebase --onto 622e88 9c68fdc
First, rewinding head to replay your work on top of it...
Applying: fourth commit
Applying: fifth commit

خوب، حالا تاریخچه جدیدمان را روی یک کامیت پایه قابل دور ریختن که حالا دستورالعملهایی درباره چگونگی بازسازی کل تاریخچه در خود دارد، بازنویسی کردهایم. میتوانیم آن تاریخچه جدید را به یک پروژه جدید push کنیم و حالا وقتی دیگران آن مخزن را کلون کنند، فقط دو کامیت اخیر و یک کامیت پایه با دستورالعملها را خواهند دید.
حالا فرض کنیم نقش کسی را داشته باشیم که برای اولین بار پروژه را کلون میکند و میخواهد کل تاریخچه را داشته باشد. برای دریافت داده تاریخچه پس از کلون کردن این مخزن کوتاه شده، باید یک ریموت دوم برای مخزن تاریخی اضافه کرد و fetch انجام داد:
$ git clone https://github.com/schacon/project
$ cd project
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
622e88e Get history from blah blah blah
$ git remote add project-history https://github.com/schacon/project-history
$ git fetch project-history
From https://github.com/schacon/project-history
* [new branch] master -> project-history/master
حالا همکار شما کامیتهای اخیرش را در شاخهی master
دارد و کامیتهای تاریخی را در شاخهی project-history/master
.
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
622e88e Get history from blah blah blah
$ git log --oneline project-history/master
c6e1e95 Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
برای ترکیب آنها، کافی است دستور git replace
را با کامیتی که میخواهید جایگزین شود و سپس کامیتی که میخواهید جایگزینش کنید، اجرا کنید.
پس ما میخواهیم کامیت «چهارم» در شاخهی master
را با کامیت «چهارم» در شاخهی project-history/master
جایگزین کنیم:
$ git replace 81a708d c6e1e95
حالا اگر تاریخچهی شاخهی master
را نگاه کنید، به این شکل به نظر میرسد:
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
جالب نیست؟ بدون اینکه لازم باشد همهی SHA-1های بالادستی را تغییر دهیم، توانستیم یک کامیت در تاریخچهمان را با کامیتی کاملاً متفاوت جایگزین کنیم و همهی ابزارهای معمول (bisect
، blame
و غیره) دقیقاً طبق انتظار ما کار میکنند.

git replace
نکتهی جالب این است که هنوز 81a708d
را به عنوان SHA-1 نشان میدهد، حتی اگر در واقع دادههای کامیت c6e1e95
که جایگزینش کردیم استفاده شود.
حتی اگر دستوری مثل cat-file
اجرا کنید، دادههای جایگزین شده را به شما نشان میدهد:
$ git cat-file -p 81a708d
tree 7bc544cf438903b65ca9104a1e30345eee6c083d
parent 9c68fdceee073230f19ebb8b5e7fc71b479c0252
author Scott Chacon <schacon@gmail.com> 1268712581 -0700
committer Scott Chacon <schacon@gmail.com> 1268712581 -0700
fourth commit
به خاطر داشته باشید که والد واقعی 81a708d
کامیت جایگزینکنندهی ما (622e88e
) بود، نه 9c68fdce
که اینجا نوشته شده است.
نکتهی جالب دیگر این است که این دادهها در مراجع ما نگهداری میشوند:
$ git for-each-ref
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/heads/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/remotes/history/master
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/HEAD
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/replace/81a708dd0e167a3f691541c7a6463343bc457040
این یعنی به راحتی میتوانیم جایگزینی خود را با دیگران به اشتراک بگذاریم، چون میتوانیم این را روی سرور خودمان پوش کنیم و دیگران به آسانی میتوانند آن را دانلود کنند. این موضوع در سناریوی الحاق تاریخچهای که اینجا بررسی کردیم چندان مفید نیست (چون همه به هر صورت هر دو تاریخچه را دانلود میکنند، پس چرا آنها را جدا کنیم؟) ولی در شرایط دیگر میتواند کاربردی باشد.