Pulling
بیشتر اوقات برای آوردنِ تغییراتِ تویِ remote repository به local repository باید از دستورِ fetch همراه با merge استفاده کنیم. (fetch + merge
)
البته دستوری به اسمِ pull
رو داریم که دو دستورِ بالا رو یکی میکنه.
در تصویرِ زیر، در ابتدا local repo و remote repo در وضعیتِ یکسانی قرار دارن و در هر دو repo فقط یک کامیت هست.
تو لوکال ریپو یه کامیتِ جدیدی رو میسازیم. و در ریموت ریپو نیز کامیتِ جدید دیگری رو میسازیم. حالا زمانی که از دستورِ git pull
استفاده میکنیم گیت کامیتِ C رو از ریموت ریپو دانلود میکنه و اون رو در لوکال ریپو جا میکنه.
دقت کنید که Origin/Master حالا به کامیتِ C اشاره میکنه. و حالا مسیرِ branchهامون از هم جدا هست. در این حالت، گیت از three-way merged استفاده میکنه تا تغییراتِ تویِ کامیتِ C (تغییراتِ remote) رو با master branchمون یکی کنه و در نتیجه یه merge commit رو خواهیم داشت. (کامیتِ M در تصویر)
برخی افراد merge commit رو نمیپسندن چون این کامیتها history رو آلوده میکنن. روشِ جایگزینی که داریم استفاده از rebasing هستش.
اگه آپشنِ rebasing در دستورِ git pull استفاده کنیم گیت کامیتِ B رو rebase خواهد کرد و baseش رو از کامیتِ A به کامیتِ C تغییر خواهد داد. و این یعنی دوباره، علاوه بر تغییراتی که از remote روی local اعمال شد تغییراتِ دیگهای نیز علاوه بر اون، با rebase کردنِ کامیتِ B اعمال شد. حالا یه تاریخچهی خطی داریم.
و سالهاست که بر سر این قضیه بحثهاست. برخی عاشقِ rebasing هستن و برخی merge commit رو ترجیح میدن.
سناریویِ بالا رو در عمل ببینیم. کامیتِ جدیدی رو در remote repo میسازیم. حالا برمیگردیم به ترمینال و local repoمون. در اینجا هم کامیتِ جدیدی رو میسازیم.
حالا به logمون نگاه کنیم.
* 77f23f4 (HEAD -> master) Add file1
* 012ff85 (origin/master, origin/HEAD) Update README.md
* fb3b343 Initial commit
با توجه به خروجیِ بالا، Master branch یه کامیت جلوتر از origin/master branch هستش. ولی در این لحظهای که لاگ بالا رو میبینیم از کامیتی که در گیتهاب ساخته شده، خبری نداریم.
حالا، اگه دستورِ git pull
رو اجرا کنیم، گیت کامیتِ جدید رو از remote repo دانلود خواهد کرد و سپس، three-way merge رو اجرا خواهد کرد تا تغییرات رو به master branch بیاره.
git pull
با اجرای دستورِ بالا ادیتورِ پیشفرض اجرا خواهد شد تا پیامِ merge commit رو ببینیم و ویرایشش کنیم.
دوباره لاگ رو یه نگاه میکنیم.
* f8dd46e (HEAD -> master) Merge branch 'master' of https://github.com/codewithmosh/Mars into master
|\
| * f11b0d0 (origin/master, origin/HEAD) Update README.md
* | 77f23f4 Add file1
|/
* 012ff85 Update README.md
* fb3b343 Initial commit
کامیتِ f8dd46e همون merge commitمونه که تغییراتِ کامیتهایِ f11b0d0 و 77f23f4 رو یکی کرده. همانطور که میبینید نتیجهی کار non-linear history هستش. میتونیم از re-basing استفاده کنیم تا یه linear history داشته باشیم. ولی قبلش آخرین کامیت (f8dd46e) رو undo میکنیم تا به آخرین وضعیتِ قبلی برسیم.
git reset --hard HEAD~1
دوباره به لاگ نگاه کنیم.
* efe2257 (HEAD -> master) Add file1
| * f11b0d0 (origin/master, origin/HEAD) Update README.md
|/
* 012ff85 Update README.md
* fb3b343 Initial commit
حالا میتونیم دستورِ git pull —-rebase
رو اجرا کنیم تا تغییراتِ localمون رو replay کنیم. دوباره یه نگاهی به لاگ بندازیم.
* 478ac2a (HEAD -> master) Add file1
* f11b0d0 (origin/master, origin/HEAD) Update README.md
* 012ff85 Update README.md
* fb3b343 Initial commit
حالا یه simple linear history داریم و کامیتِ لوکالمون بالاتر از کامیتی هست که در گیتهاب ساخته بودیم.