Merge در Git چیست و چگونه انجام میشود؟
تعریف git merge، تفاوت fast-forward و merge commit، حل Conflict، abort/continue — بر اساس git-merge docs و Pro Git Basic Branching and Merging.
Founder & product engineer

Merge یعنی پیوستن تاریخچههای توسعه به هم: تغییرات یک Commit/Branch را وارد Branch جاری کردن. مستندات git-merge میگوید این فرمان تغییرات را از زمان جدا شدن تاریخچهها تا نوک Branch نامبرده روی Branch فعلی اعمال میکند و توسط git pull هم برای ادغام کار Remote استفاده میشود.
در UIهایی مثل GitHub، دکمهٔ Merge Pull Request در نهایت همین ایده را روی سرور اجرا میکند (با استراتژیهای مختلف UI). فهم لایهٔ Git جلوی ترس از Conflict را کم میکند: Conflict یعنی Git نمیتواند خودکار تصمیم بگیرد؛ نه اینکه مخزن خراب شده است.
پیشنیاز مفهومی: Branch (۰۷۶) و Commit (۰۷۴).

پاسخ کوتاه
روی Branch مقصد بایستید و git merge <branch-مبدأ> را بزنید. اگر تاریخچهٔ شما کاملاً پشت مبدأ باشد، اغلب Fast-forward رخ میدهد (فقط اشارهگر جلو میرود). اگر هر دو طرف Commit جدا داشته باشند، یک Merge Commit با دو والد ساخته میشود مگر استراتژی/گزینه خلاف بگوید. اگر همان خطوط فایل از دو طرف عوض شده باشد، Conflict میگیرید: فایل را درست کنید، git add، سپس commit یا merge --continue.
Conflict شکست نیست؛ نقطهٔ تصمیم انسانی است جایی که ابزار حق حدس زدن ندارد.
سناریوی کلاسیک (از مستند رسمی)
مستند git-merge این تاریخچه را مثال میزند: Branch topic از master جدا شده و هر دو جلو رفتهاند. با git merge topic روی master، تغییرات topic از نقطهٔ واگرایی روی master بازپخش مفهومی میشود و Commit ادغام H با دو والد ساخته میشود. قبل از عملیات، ORIG_HEAD به نوک قبلی Branch جاری اشاره میکند تا مسیر برگشت روشنتر باشد.
Fast-forward در برابر True merge
| حالت | چه میشود | چه زمانی |
|---|---|---|
| Already up to date | هیچ | مبدأ پشت/همتراز شماست |
| Fast-forward | اشارهگر Branch جلو میرود؛ بدون Merge Commit | شما Commit اضافه ندارید |
| True merge | Merge Commit با حداقل دو والد | هر دو طرف واگرا شدهاند |
| --no-ff | حتی اگر بشود FF، Merge Commit بساز | خواستهٔ سیاست تاریخچه |
| --ff-only | فقط اگر FF ممکن است؛ وگرنه خطا | جلوگیری از Merge ناخواسته |
انتخاب --no-ff گاهی برای حفظ هویت Branch فیچر در تاریخچه استفاده میشود؛ سیاست تیم را دنبال کنید.
فرمانهای پایه
bash
git switch main git pull git merge feature-cart
اگر میخواهید قبل از Commit ادغام را بررسی کنید:
bash
git merge --no-commit feature-cart
لغو کامل وقتی Conflict یا پشیمانی دارید (با احتیاط اگر Uncommitted پیچیده دارید):
bash
git merge --abort
ادامه بعد از حل Conflict:
bash
git add . git merge --continue # یا: git commit
Conflict چگونه نمایش داده میشود؟
طبق بخش HOW CONFLICTS ARE PRESENTED در git-merge، برای تداخل متنی نشانگرهایی مثل <<<<<<< و ======= و >>>>>>> در فایل میآید. سبک diff3 با تنظیم merge.conflictStyle اصل مشترک را هم نشان میدهد و گاهی تصمیم را سادهتر میکند. فایلهای باینری تداخل را جور دیگری علامت میزنند و نیاز به انتخاب نسخه یا ابزار دارند.
- git status فهرست Unmerged را نشان میدهد.
- git diff تداخل را برجسته میکند.
- git mergetool ابزار گرافیکی/تعاملی را باز میکند.
- پس از ویرایش صحیح، حتماً add کنید وگرنه Merge تمام نمیشود.
پیششرطهای امن قبل از Merge
مستند رسمی هشدار میدهد Merge با تغییرات Uncommitted غیرساده میتواند برگشت را سخت کند. عادت سالم:
- وضعیت را Commit یا Stash کنید.
- تست/بیلد Branch مبدأ را بدانید سبز است.
- main را تازه کنید تا از پایهٔ قدیمی Merge نکنید.
- اگر ترس دارید، یک Branch پشتیبان از مقصد بگیرید.
استراتژی پیشفرض
برای ادغام یک Head، استراتژی پیشفرض مدرن ort است (در مستندات توضیح داده شده؛ recursive عملاً به آن همگرا شده). نیازی نیست روز اول همهٔ -Xها را حفظ کنید؛ وقتی rename یا تعارض فضای خالی مشکلساز شد به مستند برگردید. Octopus برای چند Head همزمان است و برای شروع لازم نیست.
Merge در برابر Rebase (مرز کوتاه)
Rebase تاریخچه را روی پایهٔ جدید بازنویسی میکند؛ Merge تاریخچه را با Commit ادغام حفظ میکند. هر دو ابزار معتبرند؛ روی Branchهای مشترک Pushشده، Rebase/Force نیاز به توافق تیم دارد. این مقاله عمداً روی Merge میماند چون مسیر پیشفرض pull و دکمهٔ بسیاری از PRهاست.
Merge از نگاه فرآیند تیمی
در GitHub flow، Merge معمولاً بعد از Review است نه قبلش. Protected Branch میتواند Merge را به وضعیت CI سبز و تأیید Reviewer مشروط کند. پاک کردن Branch بعد از Merge فهرست را تمیز میکند ولی تاریخچهٔ Commitها میماند.
برای مدیر محصول: «در حال Resolve Conflict» یعنی هزینهٔ واقعی ادغام موازیکاری؛ با کوتاهکردن عمر Branch و همگامسازی مکرر کم میشود.
چکلیست حل Conflict
- نفس عمیق؛ مخزن معمولاً قابل abort است.
- فهرست فایلهای Unmerged را از status بگیرید.
- هر فایل را با نیت محصول حل کنید نه با پاک کردن بیفکر نشانگرها.
- تست سریع همان محدوده.
- add و اتمام Merge با پیام واضح.
- اگر گیر کردید: merge --abort و کمکگرفتن، نه Forceهای ناشناخته.
جمعبندی
Merge تاریخچهها را به Branch جاری میپیوندد؛ گاهی با جابهجایی اشارهگر (FF) و گاهی با Commit ادغام. Conflict بخشی طبیعی از کار موازی است و مسیر رسمی دارد: ویرایش، add، ادامه یا abort. با Branchهای کوتاهعمر و Pull منظم، Merge کمتر دردناک میشود.
با این مقاله، بلوک پایهٔ Git سری (۰۷۰–۰۷۷) کامل میشود؛ ادامه روی PR، Review و بهداشت مخزن میرود.
پیام Merge Commit را جدی بگیرید
وقتی True merge رخ میدهد، پیام پیشفرض معمولاً نام Branch را دارد. آن را در صورت نیاز غنی کنید: چه چیزی وارد main شد و آیا Breaking change دارد؟ در تاریخچهٔ شلوغ، پیام Merge نقطهٔ پیدا کردن «کی این فیچر وارد شد» است.
اگر تیم squash merge در UI GitHub استفاده میکند، ممکن است روی main یک Commit تکی ببینید و Merge Commit کلاسیک نبینید. هر سه حالت (merge commit، squash، rebase merge) معتبرند؛ مهم توافق تیم و درک اثرشان روی تاریخچه است.
ابزارها و استراتژی حل Conflict
برای Conflictهای سخت، mergetool یا قابلیتهای سهطرفه در IDE کمک میکند. گاهی بهترین حل، صحبت با نویسندۀ تغییر دیگر است نه حدس. اگر هر دو طرف یک API را عوض کردهاند، انتخاب مکانیکی یک سمت میتواند باگ منطقی بسازد که تست سطحی نبیند.
برای فایلهای تولیدشده (lockfile، کد جنریتشده) ممکن است سیاست «یک نفر regenerate کند» بهتر از ادغام دستی باشد. این سیاست را در README بگذارید.
Merge از Remote-tracking
الگوی رایج:
bash
git fetch origin git merge origin/main
این با pull همخانواده است ولی کنترل بیشتری برای بررسی بین Fetch و Merge میدهد. روی feature Branch، Merge کردن origin/main شما را با پایه همتراز میکند تا PR تمیزتر شود.
وقتی Merge راه درست نیست
- اگر فقط میخواهید یک Commit خاص را بیاورید: cherry-pick (با آگاهی از پیامدها).
- اگر تاریخچهٔ خطی روی Branch شخصی میخواهید: rebase روی پایه — فقط قبل از اشتراک یا با توافق.
- اگر دو پروژهٔ بیربط را قاطی میکنید: --allow-unrelated-histories نادر و خطرناک برای تازهکار است.
انتخاب ابزار باید از هدف بیاید نه از عادت یوتیوب.
تمرین امن Conflict
در یک مخزن آزمایشی، دو Branch بسازید که یک خط از یک فایل را متفاوت عوض کنند، Merge کنید، Conflict را حل کنید، و یکبار هم abort را تمرین کنید. ترس Conflict با یکبار تمرین کنترلشده کم میشود. این تمرین را قبل از اولین Conflict واقعی Production انجام دهید.
پیوند به Review و CI
Merge سبز در CI بهمعنی بینقص بودن منطقی نیست، ولی فیلتر خوبی برای شکستهای آشکار است. Review انسانی روی Conflictهای معنایی تمرکز میکند. با هم، کیفیت ورود به main را بالا میبرند. مقالهٔ ۰۷۹ Code Review را بعد از این بلوک بخوانید.
اگر Mergeهای مکرر CI را قرمز میکنند، مشکل ممکن است تست شکننده یا همگامنبودن Branchها باشد نه «بد بودن Merge». ریشه را بسنجید.
جمعبندی عملی برای تیم
سیاست پیشنهادی حداقلی: Branch کوتاه، همگامسازی با main پیش از PR، Merge از مسیر Review، ممنوعیت Force روی main، و تمرین Conflict در محیط امن. با اینها، Merge از هیولا به کار عادی تبدیل میشود.
سه حالت دکمهٔ Merge در GitHub — اثر روی تاریخچه
Create a merge commit: تاریخچهٔ Branch و Merge Commit را نگه میدارد. Squash and merge: همه را در یک Commit روی پایه فشرده میکند؛ تاریخچهٔ میانی فیچر روی main نمیماند. Rebase and merge: Commitها را خطی روی پایه میچیند بدون Merge Commit. هر سه از نظر محصولی «ادغام»اند؛ از نظر شکل تاریخچه فرق دارند.
تیم باید یکی را پیشفرض کند تا log خوانا بماند. عوض کردن هفتگی استراتژی فقط سردرگمی میآورد.
Conflictهای خاص: حذف در برابر ویرایش، Rename
گاهی یک طرف فایل را حذف کرده و طرف دیگر ویرایش. Git Conflict ساختاری میدهد و باید تصمیم محصولی بگیرید: حذف بماند یا نسخهٔ ویرایششده. Renameها را استراتژی ort بهتر تشخیص میدهد، ولی همیشه بینقص نیست؛ وضعیت را دستی تأیید کنید.
فایلهای قفلشده یا باینری (تصویر، PDF) اغلب نیاز به انتخاب یک سمت کامل دارند. برای داراییهای بزرگ، سیاست ذخیره خارج از Git را بررسی کنید.
ادغامهای مکرر کوچک بهتر از یک ادغام غول
اگر دو هفته جدا کار کنید، یک Merge پایانی میتواند نیمروز بگیرد. اگر هر روز base را Merge کنید، هر Conflict کوچک و تازه است. این همان پیوند Branch کوتاه و Merge مکرر است.
در عمل: تقویم تیمی با «ساعت همگامسازی» حتی ۱۵ دقیقهای، از فریاد آخر اسپرینت کم میکند.
نشانههایی که Merge سالم است
- CI روی PR سبز قبل از Merge.
- حداقل یک Reviewer برای تغییرهای غیر بدیهی.
- پیام یا خلاصهٔ PR علت را میگوید.
- بعد از Merge، Branch پاک و main محلی Pull شده.
- مانیتورینگ بعد از Deploy مربوط به همان Merge هشیار است.
Merge فقط فرمان Git نیست؛ دروازهٔ کیفیت ورود به خط اصلی است. اگر دروازه همیشه باز باشد، تاریخچه پر از برگشتهای اضطراری میشود.
تمرین پایانی بلوک ۰۷۰–۰۷۷
- مخزن آزمایشی بسازید یا Clone کنید.
- دو Branch با تغییر متداخل بسازید.
- Merge و Resolve را یکبار کامل کنید.
- یکبار abort را تمرین کنید.
- همان کار را با یک PR روی هاست تکرار کنید.
با اتمام این تمرین، شما چرخهٔ پایهٔ همکاری Git را لمس کردهاید: تاریخچه، همگامسازی، شاخه، ادغام. بقیهٔ سری روی Review، Secret، و مستندسازی همان چرخه را بالغ میکند.
پس از Merge چه باید کرد؟
- روی ماشین خود main را Pull کنید.
- Branch فیچر را محلی و Remote پاک کنید اگر سیاست تیم است.
- اگر Deploy خودکار نیست، مسیر انتشار را آگاهانه شروع کنید.
- اگر Conflict سختی حل کردید، نکتهاش را در PR یا چت تیم برای یادگیری ثبت کنید.
- اگر رفتار Production عوض شد، همان Merge را در لاگ تغییرات مرتبط کنید.
Merge پایان کار فکری فیچر نیست؛ آغاز مسئولیت در خط اصلی است. مانیتورینگ و آمادگی Rollback بخشی از همان مسئولیتاند.
در مرور هفتگی، Mergeهای پرConflict را بررسی کنید: آیا مرز کار یا طراحی API مشکل داشته؟ بهبود فرآیند از سرزنش فرد مفیدتر است.
با این عادتها، Merge به رویداد عادی کیفیت تبدیل میشود نه صحنهٔ ترس هفتگی.
واژهنامهٔ کوچک Merge برای جلسهٔ تیم
- Fast-forward: جلو رفتن بدون Commit ادغام.
- Merge commit: گره با دو والد که ادغام را ثبت میکند.
- Conflict: تداخل تصمیمنیاز در فایل.
- Abort: لغو ادغام و برگشت به قبل.
- Squash: فشردن چند Commit در یکی هنگام ادغام در UI.
یکبار این پنج واژه را با مثال روی وایتبورد بکشید. بعد از آن، پیامهای چت مثل «کانفلیکت دارم» بهجای وحشت، درخواست کمک مشخص میشود: روی کدام فایل، بین کدام Branchها.
پایان بلوک Git پایه: از تعریف تا ادغام، شما ابزار مشترک همکاری نرمافزار مدرن را در دست دارید. تمرین منظم کوتاه، بهتر از مطالعهٔ پراکندهٔ طولانی است.
یک پاراگراف پایانی برای مدیر و توسعهدهنده
برای توسعهدهنده: Merge مهارت آرام ماندن در تداخل و تصمیمگیری روی محتواست. برای مدیر: تعداد Conflictهای سخت سیگنال طراحی و هماهنگی است نه فقط مهارت فرد. هر دو طرف با Branch کوتاهتر و همگامسازی زودتر برنده میشوند. این پایان منطقی بلوک مفاهیم پایهٔ Git در سری FutureForge است؛ ادامه را با PR و Review بگیرید.
منابع و مراجع
- git-merge documentation — https://git-scm.com/docs/git-merge
- Pro Git — Basic Branching and Merging — https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging
- GitHub Docs — About Git — https://docs.github.com/en/get-started/using-git/about-git
- GitHub Docs — Getting changes from a remote repository — https://docs.github.com/en/get-started/using-git/getting-changes-from-a-remote-repository
- Pro Git — Branches in a Nutshell — https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell
Author
Soheil Ebrahimpour is the founder of FutureForge. He works on product design, architecture, and getting custom software into production.
Related notes
If you are unsure about architecture or the build path, we can talk about the project.
Describe the problem and the constraints. If there is a fit, we will schedule a conversation.




