سرفصل‌های آموزشی
آموزش کاربردی گیت برای برنامه نویسان
Git  Merge

Git Merge

ادغام کردن (Merging) راهکار گیت برای قرار دادن یک تاریخچه ی فشرده در یک پروژه مشترک است. دستور git merge به شما اجازه می دهد که شاخه های مستقلی که با دستور git branch ایجاد کرده اید را با یک شاخه ی واحد ادغام کنید.

توجه داشته باشید که تمام دستورات پیش رو، ادغام را به شاخه فعلی انجام می دهند. شاخه فعلی بروز می شود تا ادغام انجام شده را نشان دهد. اما شاخه هدف به طور کامل تحت تاثیر قرار نخواهد گرفت. این بدان معنی است که git merge اغلب در ارتباط با git checkout برای انتخاب شاخه فعلی و git branch -d برای حذف شاخه منسوخ شده استفاده می شود.

این دستور چگونه کار می کند

دستور git merge چندین commit را به یک تاریخچه ی واحد متصل می کند. بیشتر وقت ها دستور git merge برای ترکیب دو شاخه استفاده می شود. در ادامه مثال هایی گفته می شود که بر روی الگوی ادغام شاخه ها تمرکز دارد. در این مثال ها، git merge دو اشاره گر commit را دریافت می کند که معمولا آخرین commit شاخه ها است. این دستور یک نقطه ی مشترک commit را بین آنها پیدا خواهد کرد. هنگامی که گیت یک نقطه ی مشترک را پیدا می کند، یک "merge commit" جدید ایجاد خواهد کرد که commit های هر شاخه را ترکیب می کند.

فکر کنید ما یک شاخه ی feature جدید داریم که مرجع آن شاخه main است. ما اکنون می خواهیم این شاخه ی feature را به شاخه ی main ادغام کنیم.

اجرای git merge شاخه ی feature مشخص شده را به شاخه ی فعلی ادغام می کند که در مثال ما شاخه ی main خواهد بود. گیت الگوریتم ادغام را به صورت خودکار تعیین می کند.

تفاوت Merge Commit ها در برابر سایر commit ها این است که آنها دو والد commit دارند. هنگام ایجاد یک merge commit، گیت تلاش خواهد کرد تا به صورت جادویی همه ی تاریخچه ها به صورت جداگانه برای شما ادغام شود. اگر گیت با یک قطعه داده که در هر دو تاریخچه تغییر کرده است برخورد کند، قادر نخواهد بود به طور خودکار آنها را ادغام کند. در این مواقع یک تداخل در کنترل نسخه پیش آمده و گیت نیاز به مداخله کاربر برای ادامه دادن ادغام دارد.

آماده شدن برای ادغام

قبل از انجام ادغام، چند مرحله آماده سازی وجود دارد تا اطمینان حاصل شود که ادغام به درستی انجام می شود:

  • تأیید شاخه ای که قرار است ادغام شود

اجرای دستور git status برای اطمینان از اینکه HEAD به شاخه ای که ادغام را دریافت می کند، اشاره ی کند. در صورت نیاز، دستور git checkout اجرا شود تا به شاخه ای که می خواهیم در آن ادغام کنیم برویم. در مثال ما باید دستور git checkout main اجرا شود.

  • دریافت آخرین commit ها از مخزن remote

اطمینان حاصل کنید که هر دو شاخه با آخرین تغییرات remote به روز شده باشند. برای دریافت آخرین commit ها از مخزن remote باید دستور git fetch را اجرا کرد. پس از اتمام دستور git fetch، اطمینان حاصل کنید که شاخه اصلی آخرین به روز رسانی ها را با اجرای دستور git pull انجام می دهد.

  • ادغام کردن

پس از گذراندن مراحل آماده شدن برای ادغام می توانیم دستور git merge x را اجرا کنیم. x نام شاخه ای است که می خواهیم ادغام کنیم.

ادغام سریع رو به جلو

ادغام سریع رو به جلو زمانی می تواند رخ دهد که یک مسیر خطی از نوک شاخه فعلی به شاخه هدف وجود دارد. به جای ادغام واقعی شاخه ها، تمام کاری که گیت باید برای ادغام انجام دهد، جا به جایی نوک شاخه فعلی به نوک شاخه هدف است. این کار به طور موثری تاریخچه ها را ترکیب می کند، زیرا تمام commit های شاخه هدف در حال حاضر از طریق شاخه ی فعلی در دسترس هستند. به عنوان مثال، ادغام سریع رو به جلو از یک شاخه ی feature به شاخه ی main چیزی شبیه به موارد زیر است:

با این حال، اگر شاخه ها از بین بروند، ادغام سریع رو به جلو ممکن نیست. هنگامی که مسیر خطی ای به شاخه هدف وجود نداشته باشد، گیت هیچ انتخابی جز اینکه آنها را از طریق ادغام 3 طرفه ترکیب کند ندارد. ادغام 3 طرفه از یک commit اختصاصی برای اتصال دو تاریخچه استفاده می کند.

در حالی که شما می توانید از هر یک از این استراتژی های ادغام استفاده کنید، بسیاری از توسعه دهندگان مایل به استفاده از ادغام سریع رو به جلو برای ویژگی های کوچک و یا رفع اشکال هستند، در حالی که از ادغام سه طرفه برای ادغام ویژگی های بزرگ تر استفاده می کنند. در مورد دوم، نتیجه ی merge commit به عنوان یک پیوست نمادین از دو شاخه عمل می کند.

مثال اول ما یک ادغام سریع رو به جلو را نشان می دهد. کد زیر یک شاخه جدید ایجاد می کند، دو commit را به آن می افزاید، سپس آن را به خط اصلی با ادغام سریع رو به جلو ادغام می کند.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

این یک گردش کار مشترک برای شاخه هایی با هدف کوتاه مدت است که بیشتر به عنوان یک توسعه جداگانه استفاده می شود تا یک ابزار سازمان دهنده برای ویژگی های بزرگ تر.

همچنین توجه داشته باشید که گیت نباید در مورد دستور git branch -d هیچ شکایتی کند، زیرا شاخه ی new-feature در حال حاضر از شاخه main قابل دسترسی است.

در صورتی که شما نیاز به merge commit در طول ادغام سریع رو به جلو برای نگه داشتن سوابق اهدافتان داشتید می توانید دستور git merge  را همراه با گزینه ی no-ff-- اجرا کنید.

git merge --no-ff <branch>

این دستور شاخه مشخص شده را به شاخه فعلی ادغام می کند، اما همیشه یک merge commit را ایجاد می کند (حتی اگر ادغام سریع رو به جلو باشد). این برای مستند سازی تمام ادغام هایی که در مخزن شما رخ می دهد مفید است.

ادغام 3 طرفه 

مثال بعدی بسیار مشابه قبلی است، اما نیاز به ادغام 3 طرفه دارد، زیرا در حالی که این شاخه ی feature در حال پیشرفت است شاخه ی  main هم پیشرفت هایی کرده است. این یک اتفاق رایج برای پیاده سازی ویژگی های بزرگ و یا زمانی که چندین توسعه دهنده به طور همزمان بر روی یک پروژه کار می کنند است.

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

توجه داشته باشید که انجام ادغام سریع رو به جلو برای گیت غیر ممکن است، زیرا هیچ راهی برای حرکت شاخه ی main به شاخه ی new-feature بدون عقب نشینی وجود ندارد.

در اکثر گردش کارها، new-feature یک ویژگی بسیار بزرگ است که مدت زمان زیادی برای توسعه نیاز دارد، به همین دلیل است که commit های جدید در شاخه ی main به وجود می آید.

حل کردن تداخل ها 

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

بخش بزرگی از فرآیند ادغام گیت این است که از گردش کار آشنای edit/stage/commit برای حل تداخل های ادغام استفاده می کند. هنگامی که شما با یک تداخل در ادغام روبرو می شوید، دستور git status به شما نشان می دهد که کدام فایل ها دچار تداخل هستند. به عنوان مثال، اگر هر دو شاخه یک بخش از فایل hello.py را اصلاح کرده اند، شما چیزی شبیه به موارد زیر را مشاهده خواهید کرد:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

تداخل ها چگونه نمایش داده می شوند

هنگامی که گیت در روند یک ادغام با تداخل مواجه می شود، محتوای فایل های آسیب دیده را با شاخص های بصری ویرایش می کند که هر دو طرف، محتوای متضاد را نشان می دهند. این نشانگرهای بصری عبارتند از: <<<<<<<, ======= و >>>>>>>. این نشانگر ها برای جستجو در پروژه برای یافتن و برطرف کردن جایی که تداخل در طول ادغام در آن جا رخ داده مفید است.

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

به طور کلی محتوای قبل از نشانگر ======= شاخه ی دریافت کننده است و محتوای بعد از آن نشانگر بخشی از شاخه ادغام شونده است.

هنگامی که بخش های تداخل خورده را شناسایی کردید، می توانید به سراغ آنها رفته و ادغام را به دلخواه خود تنظیم کنید. هنگامی که شما آماده برای پایان دادن به ادغام هستید، تمام کاری که باید انجام دهید این است که git add را اجرا کنید تا به گیت اعلام شود که تداخل ها پایان یافته است. سپس، یک git commit معمولی را اجرا می کنید تا merge commit ایجاد شود.

توجه داشته باشید که تداخل تنها در صورت ادغام 3 طرفه رخ می دهد. امکان به وجود آمدن تداخل در ادغام سریع رو به جلو وجود ندارد.

جمع بندی

این مقاله یک مرور کلی بر دستور git merge بود. ادغام یک فرآیند ضروری در هنگام کار با گیت است. در این مقاله از مکانیسم موجود در پشت ادغام و تفاوت بین ادغام سریع رو به جلو و ادغام 3 طرفه بحث کردیم. برخی از نکات کلیدی که گفته شد عبارت است از:

  • ادغام گیت، دنباله ای از commit ها را با یک تاریخچه ی واحد از commit ترکیب می کند.
  • دو راه اصلی برای ادغام در گیت وجود دارد: ادغام سریع رو به جلو و ادغام سه طرفه
  • گیت می تواند به طور خودکار merge commit را ایجاد کند، مگر اینکه تغییراتی در هر دو دنباله از commit ها وجود داشته باشد که باعث ایجاد تداخل شود.

منبع:

https://www.atlassian.com/git/tutorials/using-branches/git-merge

online-support-icon