Git
Chapters ▾ 2nd Edition

3.5 شاخه‌سازی در گیت - برنچ‌های ریموت

برنچ‌های ریموت

مراجع یا رفرنس‌های ریموت (Remote/دوردست)، مراجع (نشانگرهایی) در مخزن ریموت شما هستند که شامل برنچ‌ها، تگ‌ها و غیره می‌شود. شما می‌توانید لیست کاملی از مراجع ریموت را با git ls-remote <remote> یا git remote show <remote> (برای برنچ‌های ریموت و اطلاعات بیشتر) مشاهده کنید. گرچه شایان ذکر است که روش رایج‌تر استفاده از برنچ‌های درپی-ریموت (Remote-tracking) است.

برنچ‌های درپی-ریموت، رفرنس‌هایی به وضعیت برنچ‌های ریموت هستند. آنها رفرنس‌های محلی هستند که نمی‌توانید جابه‌جا کنید؛ هر گاه که هر ارتباط شبکه‌ای برقرار کنید، گیت آنها را برای شما جابه‌جا می‌کند تا از اینکه آنها به دقت وضعیت مخزن ریموت را بازنمایی می‌کنند، اطمینان حاصل کند. می‌توانید به آنها مثل بوک‌مارک بنگرید که به شما یادآوری می‌کنند که آخرین بار که به مخزن‌های ریموت وصل شدید، برنچ‌ها کجا قرار داشته‌اند.

نام برنچ‌های در پی ریموت به این صورت شکل می‌گیرد: <remote>/<branch>. به طور مثال اگر می‌خواهید ببینید آخرین بار که با ریموت origin ارتباطی داشته‌اید برنچ master کجا قرار داشته، باید به بررسی برنچ origin/master بپردازید. با همکاری روی یک ایشو کار می‌کرده‌اید و آنها روی برنچ iss53 پوش کرده‌اند و ممکن است که شما هم برنچ iss53 محلی خودتان را داشته باشید. در این حالت برنچ روی سرور با برنچ درپی-ریموت origin/iss53 به نمایش در می‌آید.

این مسئله کمی گیج‌کننده است، پس بیایید به یک مثال نگاهی بیاندازیم. فرض کنیم که یک سرور گیت به آدرس git.ourcompany.com روی شبکهٔ خود دارید. اگر از این آدرس کلون کنید، دستور clone گیت به طور خودکار آنرا origin برای شما نامگذاری می‌کند، تمام اطلاعاتش را پول می‌کند، نشانگری به جایی که برنچ master است می‌سازد و نام آنرا origin/master می‌‌گذارد. علاوه بر این گیت به شما برنچ محلی master خودتان را می‌دهد که از همان‌جایی که برنچ master در origin قرار دارد شروع می‌شود، تا بتوانید روی آن کار کنید.

Note
“origin” چیز خاصی نیست

دقیقاً همانگونه که نام برنچ “master” هیچ معنی خاصی در گیت ندارد، “origin” هم بی‌معناست. “master” نام پیش‌فرض یک برنچ آغازین به هنگام اجرای git init است و تنها به همین دلیل بسیار مورد استفاده قرار می‌گیرد. درست به همان شکل، “origin” نام پیش‌فرض یک ریموت به هنگام اجرای git clone است. اگر git clone -o booyah را وارد کنید، آنگاه booyah/master را به عنوان برنچ پیش‌فرض ریموت خود خواهید دید.

Server and local repositories after cloning.
Figure 29. مخازن سرور و محلی بعد از کلون کردن

اگر روی برنچ master محلی خود کار کنید و در همین حین شخص دیگری به git.ourcompany.com پوش کند و برنچ master مخزن را بروزرسانی کند، آنگاه تاریخچه‌های شما به طور متفاوتی به جلو حرکت می‌کند. علاوه بر آن تا زمانی که بی‌ارتباط با سرور origin باقی بمانید، نشانگر origin/master تکان نمی‌خورد.

Local and remote work can diverge.
Figure 30. کارهای روی مخزن محلی و ریموت می‌تواند دوشاخه شود

برا همگام‌سازی کارتان با هر ریموتی، باید دستور git fetch <remote> اجرا کنید (در این مورد git fetch origin). این دستور سروری که با نام “origin” است را بررسی می‌کند (در این مثال آدرس git.ourcompany.com)، اطلاعات جدید را فچ (Fetch/واکشی) می‌کند و پایگاه‌داده محلی را بروز می‌کند که باعث جابه‌جایی نشانگر origin/master به مکان بروزترش می‌شود.

`git fetch` updates your remote references.
Figure 31. git fetch برنچ‌های درپی-ریموت‌تان را به روز می‌کند

برای نمایش داشتن چند برنچ و اینکه چه برنچی برای پروژه‌های ریموت در کجا قرار دارد، بیاید فرض کنیم که شما یک سرور گیت داخلی دیگر دارید که فقط برای توسعه با یکی از اعضای تیم «دور» (Sprint) فعلی شما پاسخگو است. این سرور در git.team1.ourcompany.com قرار دارد. همانگونه که در پایه‌های گیت بررسی شد، می‌توانید با git remote add آنرا به عنوان یک مرجع ریموت جدید به پروژه‌ای که در حال حاضر روی آن کار می‌کنید اضافه کنید. این ریموت را teamone بنامید که مختصری از آدرس کامل ریموت است.

Adding another server as a remote.
Figure 32. اضافه کردن سروری جدید به عنوان ریموت

اکنون می‌توانید git fetch teamone را اجرا کنید تا هرچیزی را که هنوز شما ندارید از سرور ریموت teamone واکشی کند. از آنجایی که اکنون سرور فقط زیرمجموعه‌ای از اطلاعات سرور origin را دارد، گیت داده‌ای را واکشی نمی‌کند بلکه یک برنچ درپی-ریموت با نام teamone/master می‌سازد که به کامیتی که teamone در master خود دارد اشاره می‌کند.

Remote tracking branch for `teamone/master`.
Figure 33. برنچ درپی-ریموت teamone/master

پوش‌کردن

هنگامی که می‌خواهید برنچی را با جهان به اشتراک بگذارید، نیاز دارید آنرا به برنچی در ریموتی که در آن اجازهٔ نوشتن دارید پوش کنید. برنچ‌های محلی شما به طور خودکار با ریموتی که به آنها بگویید همگام نمی‌شوند — باید به صراحت، برنچ‌هایی را که می‌خواهید به اشراک بگذارید، به سرور پوش کنید. از این طریق می‌توانید از برنچ‌های شخصی که برای کار دارید و نمی‌خواهید آنها را به اشتراک بگذارید استفاده کنید و فقط برنچ‌های موضوعی که می‌خواهید روی آنها مشارکت صورت گیرد را پوش کنید.

اگر برنچی با نام serverfix داشته باشید که بخواهید روی آن با دیگران مشارکت و همکاری داشته باشید، می‌توانید آنرا به همان طریقی که برنچ اول خود را پوش کردید پوش کنید. اجرا git push <remote> <branch>:

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

این به نوعی یک میانبر است. گیت به طور خودکار نام برنچ serverfix را به refs/heads/serverfix:refs/heads/serverfix گسترش می‌دهد که به معنی عبارت روبرو است: «برنچ محلی serverfix من را بگیر و برای بروزرسانی برنچ serverfix ریموت آنرا پوش کن.» در Git Internals مروری بر بخش refs/heads/ می‌اندازیم ولی به طور کل می‌توانید آنرا نادیده بگیرید. همچنین می‌توانید git push origin serverfix:serverfix کنید که همان کار را می‌کند — می‌گوید: «serverfix مرا بگیر و serverfix ریموت قرار بده.» اگر نمی‌خواهید روی ریموت serverfix نامیده شود می‌توانید به جای آن، git push origin serverfix:awesomebranch را برای پوش کردن برنچ serverfix محلیتان به aweseomebranch روی پروژه ریموت اجرا کنید.

Note
هر برا رمز خود را تایپ نکنید

اگر از یک HTTPS URL برای پوش کردن استفاده می‌کنید، سرور گیت از شما رمز و نام کاربریتان را برای احراز هویت می‌خواهد. به طور پیش‌فرض در ترمینال به شما آگهی می‌دهد تا این اطلاعات را بخواند تا سرور بتواند تشخیص دهد که شما اجازه دارید پوش کنید یا خیر.

اگر نمی‌خواهید هر بار که پوش می‌کنید آنها را تایپ کنید می‌توانید یک «کش گواهی» انجام دهید. ساده‌ترین راه برای ذخیرهٔ گواهی در حافظه به مدت چند دقیقه است، که می‌توانید به سادگی با اجرای git config --global credential.helper cache آنرا تنظیم کنید.

برای اطلاعات بیشتر روی تنظیمات کش‌کردن گواهی‌های مختلف موجود به Credential Storage مراجعه کنید.

دفعهٔ بعد که یکی از همکاران شما از سرور فچ می‌کند، یک رفرنس با نام origin/serverfix به مکان نسخهٔ serverfix سرور دریافت می‌کند:

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

مهم است که به خاطر داشته باشید که هنگامی فچی می‌کنید که برنچ‌های درپی-ریموت جدیدی را واکشی می‌کند، به طور خودکار یک نسخه قابل ویرایش محلی از آنها را نخواهید داشت. به بیان دیگر، در این مثال، شما یک برنچ serverfix جدید ندارید — شما فقط یک نشانگر origin/serverfix خواهید داشت که قابل ویرایش نیست.

برای ادغام این کار با برنچ فعال حاضر می‌توانید git merge origin/serverfix را اجرا کنید. اگر می‌خواهید که برنچ serverfix خود را داشته باشید تا روی آن کار کنید می‌توانید آنرا از جایی که برنچ درپی-ریموت فعلی هست شروع کنید:

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

این کار به شما یک برنچ محلی در جایی که origin/serverfix است، می‌دهد که می‌توانید روی آن کار کنید.

پیگیری برچ‌ها

چک‌اوت کردن یک برنچ محلی از یک برنچ درپی-ریموت به طور خودکار ماهیتی به نام «برنچ پیگیر»(Tracking) می‌سازد (و برنچی که این برنچ در حال پیگیری آن است «برنچ بالادست»(Upstream/آپ‌ستریم) نامیده می‌شود). برنچ‌های پیگیر برنچ‌های محلی هستند که رابطهٔ مستقیمی با یک برنچ ریموت دارند. اگر روی یک برنچ پیگیر باشید و git pull را تایپ کنید، گیت به طور خود به خودی می‌داند که از چه سروری فچ کند و با چه برنچی آنرا ادغام کند.

وقتی یک مخزن را کلون می‌کنید، عموماً به طور خودکار برنچ master ساخته می‌شود که پیگیر origin/master است. هرچند شما می‌توانید در صورت تمایل برنچ‌های پیگیر دیگری را نیز راه‌اندازی کنید — آنهایی که درپی برنچ‌های ریموت‌های دیگر هستند یا آنهایی که برنچ master را پیگیری نمی‌کنند. نمونهٔ سادهٔ آن مثالی است که همین الآن ملاحظه کردید: git checkout -b <branch> <remote>/branch> این عملیات آنقدر رایج است که گیت اختصار --track را هم ارائه می‌کند:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

در حقیقت این کار به حدی رایج است که حتی اختصاری هم برای آن اختصار وجود دارد. اگر نام برنچی که سعی در چک‌اوت کردن آن دارید (a) وجود ندارد و (b) دقیقاً با نام یک برنچ فقط در یک ریموت تطابق دارد، گیت برنچ پیگیر آنرا برای شما می‌سازد:

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

برای راه‌اندازی یک برنچ محلی با نامی متفاوت از برنچ ریموت، می‌توانید به آسانی از نسخه اول دستور با یک نام متفاوت برنچ محلی استفاده کنید:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'

حال برنچ محلی sf شما به طور خودکار از origin/serverfix پول می‌کند.

اگر از قبل یک برنچ محلی دارید و می‌خواهید که آنرا به یک برنچ ریموت که تازه پول کردید نسبت دهید یا هر گاه که خواستید به طور صریح که می‌خواهید برنچ بالادست برنچ پیگیر فعلی را تغییر دهید، می‌توانید از آپشن -u یا --set-upstream-to برای git branch استفاده کنید.

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Note
اختصار بالادست

هنگامی که یک برنچ پیگیر تنظیم شده دارید می‌توانید با اختصار @{upstream} یا @{u} به آن مراجعه کنید. بنابراین اگر در برنچ master هستید و در پی برنچ origin/master هستید، اگر مایلید می‌توانید دستوری مثل git merge @{u} را به جای git merge origin/master اجرا کنید.

اگر می‌خواهید بدانید که چه برنچ‌های پیگیری راه‌اندازی کرده‌اید می‌توانید از آپشن -vv برای git branch استفاده کنید. این کار تمام برنچ‌های محلی را با اطلاعات بیشتری، از قبیل اینکه هر برنچ پیگیر چه برنچی است و آیا برنچ محلی عقب‌تر، جلو‌تر یا عقب-جلوی برنچ ریموت است، لیست می‌کند.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] Add forgotten brackets
  master    1ae2a45 [origin/master] Deploy index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] This should do it
  testing   5ea463a Try something new

در اینجا می‌توان دید که برنچ iss53 ما پیگیر origin/iss53 است و دو تا «جلوتر» از آن است، به این معنی که ما دو کامیت محلی داریم که هنوز به سرور پوش نکرده‌ایم. همچنین می‌توان دید که برنچ master ما پیگیر origin/master است و بروز می‌باشد. سپس می‌توان دید که برنچ serverfix ما پیگیر برنچ server-fix-good روی سرور teamone ماست و سه کامیت و جلوتر و یکی عقب‌تر است، به این معنا که یک کامیت روی سرور هست که ما هنوز آنرا مرج نکرده‌ایم و سه کامیت محلی داریم که آنرا را پوش نکرده‌ایم. در آخر می‌توان دید که برنچ testing ما پیگیر هیچ برنچ ریموتی نیست.

البته بسیار مهم است به خاطر داشته باشید که این ارقام صرفاً از آخرین باری که هر سرور را فچ کرده‌اید مانده‌اند. همچنین این دستور به سرورها نمی‌رود، فقط به شما چیزی را می‌گیود که از این سرورها کش کرده است. اگر می‌خواهید تمام اطلاعات بروز باشند باید پیش از اجرای این دستور همهٔ ریموت‌ها را فچ کنید. بدین شکل می‌توانید این کار را انجام دهید:

$ git fetch --all; git branch -vv

پول‌کردن

مادامی که دستور git fetch تمام تغییرات سرور را واکشی می‌کند که شما ندارید، پوشهٔ کاری شما را به هیچ عنوان ویرایش نمی‌کند. به بیان ساده‌تر اطلاعات را برای شما به دست می‌آورد و به شما اجازه می‌دهد خودتان مرج را انجام دهید. هرچند دستوری به نام git pull وجود دارد که به طور ساده git fetch است که در اکثر مواقع مستقیماً پس از آن git merge اجرا می‌شود. اگر آنطور که در بخش قبل اشاره شد، برنچ پیگیری را راه‌اندازی کرده‌اید یا به طور صریح آنرا معرفی کرده‌اید یا گیت آنرا با دستورات clone یا checkout برای شما ساخته است، git pull به دنبال اینکه چه سرور و برنچی را پیگیری می‌کنید می‌گردد، آن سرور را برای شما فچ می‌کند و سپس سعی در مرج کردن آن برنچ ریموت می‌کند.

عموماً بهتر است که به طور صریح از دو دستور fetch و merge استفاده کنید چرا که git pull غالباً می‌تواند گیج‌کننده واقع شود.

پاک کردن برنچ‌های ریموت

فرض کنید که کارتان با یک برنچ ریموت تمام شده است — فرض کنیم که شما و همکاران شما کارتان روی یک ویژگی تمام شده و آنرا به برنچ master ریموت مرج کرده‌اید (یا هر برنچی که کد باثباتتان در آن است). شما می‌توانید برنچ ریموت را با آپشن --delete دستور git push پاک کنید. اگر می‌خواهید که برنچ serverfix خود را از سرور پاک کنید، باید دستور زیر را اجرا کنید:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

به طور کل تمام کاری که این دستور می‌کند این است که نشانگر برنچ را از سرور پاک کند. عموماً سرور گیت تمام داده‌ها را تا زمانی که Grabage Collector اجرا شود نگه‌داری می‌کند، تا اگر اشتباهی این پاک‌سازی رخ داده بود بازیابی آن آسان باشد.