Git
Chapters ▾ 2nd Edition

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

شاخه‌های ریموت

مراجع یا رفرنس‌های ریموت، مراجع (نشانگرهایی) در مخزن ریموت شما هستند که شامل برنچ‌ها، تگ‌ها و غیره می‌شود. شما می‌توانید لیست کاملی از مراجع ریموت را با 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 قرار دارد شروع می‌شود، تا بتوانید روی آن کار کنید.

یادداشت
«origin» خاص نیست

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

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

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

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

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

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

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

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

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

Remote tracking branch for `teamone/master`.
نمودار 34. برنچ درپی-ریموت 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 روی پروژه ریموت اجرا کنید.

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

اگر از یک 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.
یادداشت
اختصار بالادست

هنگامی که یک برنچ پیگیر تنظیم شده دارید می‌توانید با اختصار @{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 اجرا شود نگه‌داری می‌کند، تا اگر اشتباهی این پاک‌سازی رخ داده بود بازیابی آن آسان باشد.