Future ForgeFuture ForgeFuture ForgeFuture Forge
خدماتنمونه‌کارهاپکیج‌هاابزارهای رایگانیادداشت‌هادرباره ماتماس
شروع پروژه
  1. خانه
  2. /یادداشت‌ها
Future ForgeFuture Forge

استودیوی مهندسی محصول — طراحی، ساخت و استقرار نرم‌افزار.

پروژه‌تان را مطرح کنید

ارتباط

hello@futureforge.ir09128464105
Future ForgeFuture Forge

استودیوی مهندسی محصول — طراحی، ساخت و استقرار نرم‌افزار.

خدمات

طراحی و ساخت محصولتوسعه فول‌استکممیزی مهندسیمشاوره معماریزیرساخت و استقرارهوش مصنوعی در محصول

کاوش

نمونه‌کارهایادداشت‌هاپرسش‌هاپکیج‌ها

ابزارهای رایگان

ممیزی مهندسیمشاور معماریتخمین پروژهابزار پرامپت

شرکت

درباره ماتماسحریم خصوصیشرایط استفاده

پروژه‌تان را مطرح کنید

مسئله و محدودیت را بنویسید. اگر تطابق داشته باشیم، برای گفتگو هماهنگ می‌کنیم.

پروژه‌تان را مطرح کنید

ارتباط

hello@futureforge.ir09128464105
GitHubLinkedIn

© 2026 FutureForge. همه حقوق محفوظ است.

خانهخدماتابزارهای رایگانشروع پروژه
واژه‌نامه

Merge در Git چگونه کار می‌کند؟ Fast-forward، سه طرفه و Commit ادغام

مکانیک git merge: جد مشترک، fast-forward، ادغام سه طرفه و merge commit — چه زمانی تاریخچه خطی می‌ماند و چه زمانی گره ادغام ساخته می‌شود؛ از Pro Git.

سا
سهیل ابراهیم‌پور

بنیان‌گذار و مهندس محصول

·۲۹ شهریور ۱۴۰۵·7 دقیقه مطالعه
اسکچ merge دو خط و استیکی Merge

Merge پاسخ به این مسئله است: دو خط توسعه از یک جد مشترک جدا شده‌اند و حالا باید یک تاریخچهٔ واحد قابل استفاده بسازیم. برخلاف کپی دستی فایل‌ها، Git با پیدا کردن ancestor مشترک و ترکیب تغییرات، سعی می‌کند نتیجه را خودکار بسازد. وقتی نتواند، Conflict می‌دهد (۲۰۷) — نه اینکه بی‌صدا یکی را overwrite کند.

مقالهٔ ۰۷۷ معرفی مفهومی داشت؛ اینجا مکانیک: fast-forward در برابر merge commit، ادغام سه طرفه، و پیامد هر کدام برای تاریخچه و PR.

fast-forward در برابر three-way merge

پاسخ کوتاه

git merge تغییرات یک Branch را وارد Branch جاری می‌کند. اگر Branch جاری جد مستقیم دیگری باشد، اغلب fast-forward رخ می‌دهد: فقط اشاره‌گر جلو می‌رود و Commit جدیدی لازم نیست. اگر هر دو طرف جلو رفته باشند، Git سه طرفه Merge می‌کند (پایه = جد مشترک، دو نوک) و معمولاً یک merge commit با دو والد می‌سازد مگر استراتژی/گزینهٔ دیگری بخواهید.

Merge تاریخچه را حفظ می‌کند که «این دو خط اینجا به هم رسیدند»؛ این آگاهی برای دیباگ گاهی از خطی بودن صرف باارزش‌تر است.

پیش‌نیاز ذهنی: جد مشترک

Git از روی گراف Commit نزدیک‌ترین جد مشترک (merge base) را پیدا می‌کند. تفاوت‌های هر سمت نسبت به آن پایه محاسبه می‌شود. اگر هر دو سمت یک ناحیهٔ یکسان را به شکل ناسازگار عوض کرده باشند، Conflict.

bash

git switch main git merge feature/x git log --oneline --graph --decorate -n 15

حالت ۱: Fast-forward

فرض: main روی C1 است؛ feature از C1 به C2 و C3 رسیده و main جلو نرفته. Merge feature به main می‌تواند اشاره‌گر main را به C3 حرکت دهد. تاریخچه خطی می‌ماند؛ merge commit ساخته نمی‌شود.

  • مزیت: ساده و خوانا.
  • محدودیت: رد پای «اینجا فیچر ادغام شد» به‌صورت Commit جدا نیست.
  • کنترل: --no-ff مجبور به ساخت merge commit می‌کند حتی وقتی fast-forward ممکن است — بعضی تیم‌ها برای ردیابی PR این را می‌خواهند.

حالت ۲: ادغام سه طرفه و merge commit

اگر main هم Commitهای جدید داشته باشد، fast-forward ممکن نیست. Git تغییرات دو سمت را نسبت به پایه ترکیب می‌کند. نتیجهٔ موفق یک Commit ادغام با دو والد است: یکی والدین main قبلی، یکی نوک feature.

استراتژی پیش‌فرض در عمل رایج ort/recursive برای دو سر است. موارد خاص (بیش از دو Branch) کمتر در روزمره لازم است.

جدول: انتخاب‌های Merge از دید تاریخچه

روشتاریخچهچه زمانی رایج است
Fast-forwardخطیBranch کوتاه، main ثابت مانده
Merge commit (--no-ff)گره ادغام واضحردیابی PR / فیچر
Squash merge (روی هاست)یک Commit روی هدفتاریخچهٔ main خلوت
Rebase سپس merge FFخطی‌شدهقبل از ادغام روی Branch خودتان

Squash روی GitHub یک Commit واحد از کل PR می‌سازد؛ از نظر Git محلی، جزئیات متفاوت است ولی هدف محصولی «main تمیز» است. مقایسهٔ عمیق‌تر با Rebase در ۲۱۱.

Merge محلی در برابر دکمهٔ Merge در Pull Request

روی GitHub سه حالت رایج: merge commit، squash، rebase-and-merge. هر کدام تاریخچهٔ main را differently شکل می‌دهند. قبل از انتخاب پیش‌فرض مخزن، با تیم توافق کنید؛ عوض کردن مداوم عادت Review را به هم می‌زند.

مستندات GitHub About pull request merges این گزینه‌ها را شرح می‌دهد. مهم: Rebase-and-merge روی هاست با git rebase محلی یکی نیست در جزئیات UX، ولی ایدهٔ خطی‌سازی مشترک است.

آماده‌سازی قبل از Merge

  1. Working tree تمیز یا Stash؛ Merge روی تغییرات کثیف هم‌پوشان ممکن است رد شود.
  2. تست و CI سبز روی PR.
  3. به‌روز بودن نسبی با پایه (main) برای کاهش Conflict.
  4. خواندن diff نهایی؛ Merge خودکار ≠ درست بودن محصول.

اشتباه‌های رایج

  • Merge کردن بدون دیدن --graph و فهمیدن fast-forward یا نه.
  • حل سرسری Conflict و Commit ادغام با پیام خالی.
  • Merge کردن Branch اشتباه به main به‌خاطر switch فراموش‌شده.
  • فرض اینکه Merge همیشه باید Rebase باشد یا برعکس — معیار تیم.

خواندن نتیجه با graph

بعد از هر ادغام غیرپیش‌پاافتاده، یک نگاه به گراف از ده پیام گنگ در چت مفیدتر است:

bash

git log --oneline --graph --decorate --all -n 20

Fast-forward را به‌صورت خط صاف می‌بینید؛ merge commit را به‌صورت گره با دو والد. این عادت هزینهٔ «پس الان روی کدام پایه هستیم؟» را کم می‌کند.

استراتژی و گزینه‌های کاربردی

  • git merge --ff-only: فقط اگر fast-forward ممکن باشد؛ وگرنه شکست — مفید برای سیاست خطی سخت.
  • git merge --no-ff: همیشه merge commit — ردیابی فیچر.
  • git merge --abort: خروج از ادغام ناتمام.
  • پیام Commit ادغام را خالی نگذارید اگر دلیل غیرعادی دارد (مثلاً revert نسبی).

جزئیات استراتژی‌های نادر (octopus و مانند آن) برای روزمره لازم نیست؛ اول توپولوژی دو سر را مسلط شوید.

Merge و CI: تعریف «سبز»

Merge موفق در Git فقط یعنی درخت فایل بدون Conflict ساخته شد. سبز بودن تست، امنیت وابستگی، و تأیید محصول لایه‌های بعدی‌اند. دکمهٔ Merge در PR باید پشت required checks باشد تا «ادغام متنی» با «قابل انتشار» یکی گرفته نشود.

Merge base را خودتان ببینید

bash

git merge-base main feature/x git log --oneline $(git merge-base main feature/x)..feature/x

دیدن بازهٔ Commitهایی که واقعاً وارد می‌شوند، قبل از Merge، غافلگیری Review را کم می‌کند. اگر بازه بیش از حد بزرگ است، قبل از ادغام به main روی شکستن PR فکر کنید.

Revert یک merge commit

برگرداندن merge commit با git revert -m نیاز به دانستن والد اصلی دارد. این عملیات پیشرفته‌تر از Revert ساده است؛ برای حادثهٔ Production گاهی لازم می‌شود. جزئیات undo در ۲۱۳؛ اینجا فقط بدانید merge commit ردپای قابل رجوع می‌سازد که یکی از دلایل ترجیح --no-ff در بعضی تیم‌هاست.

وقتی fast-forward نمی‌خواهید

بعضی تیم‌ها عمداً --no-ff می‌زنند تا هر فیچر یک گره ادغام داشته باشد و بتوان با git log --merges یا ابزار Release یادداشت ساخت. هزینه: تاریخچه کمی شلوغ‌تر. اگر squash را روی هاست انتخاب کنید، همان ردیابی را به صفحهٔ PR می‌سپارید نه به گراف Commit.

انتخاب بین این‌ها باید مکتوب باشد؛ تغییر هفته‌به‌هفته فقط ابزار را عوض می‌کند نه کیفیت را.

Merge از دید Incident

در حادثه، سؤال «کدام Merge این را آورد؟» با merge commit یا با لینک PR پاسخ داده می‌شود. اگر همه چیز squash شده و پیام‌ها مبهم باشند، پاسخ طولانی‌تر می‌شود. بنابراین حتی وقتی squash می‌کنید، پیام نهایی و لینک PR را جدی بگیرید — جزئی از مکانیک انسانی Merge است.

سوالات متداول

آیا merge commit زشت است؟

خیر؛ اطلاعات توپولوژی می‌دهد. اگر تیم تاریخچهٔ کاملاً خطی می‌خواهد، سیاست FF-only یا rebase را صریح کنید.

Abort چگونه است؟

اگر Merge ناتمام است: git merge --abort (در صورت مجاز بودن وضعیت). بعد از Commit ادغام، برگشت معمولاً با revert merge یا reset محتاطانه است — روی مشترکات خطرناک.

Merge از Remote؟

ابتدا Fetch، سپس merge origin/main (یا Pull). Pull فقط میان‌بر است؛ فهم جداگانهٔ Fetch و Merge کنترل بیشتری می‌دهد.

خلاصه

Merge با جد مشترک کار می‌کند: یا اشاره‌گر را fast-forward می‌کند یا نتیجهٔ سه طرفه را در merge commit می‌نشاند. انتخاب FF، --no-ff، squash یا مسیر rebase به اولویت خوانایی، ردیابی PR و عادت تیم بستگی دارد — مطلق «بهترین» وجود ندارد.

وقتی ترکیب خودکار شکست بخورد، سراغ ۲۰۷ بروید؛ برای جایگزینی خطی‌سازی سراغ ۲۱۰ و ۲۱۱.

منابع و مراجع

  • Pro Git — Basic Merging — https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging
  • git-merge documentation — https://git-scm.com/docs/git-merge
  • GitHub Docs — About pull request merges — https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges
  • Pro Git — Advanced Merging — https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging
  • git-merge-base documentation — https://git-scm.com/docs/git-merge-base

نویسنده

سا

سهیل ابراهیم‌پور بنیان‌گذار FutureForge است. روی طراحی محصول، معماری و استقرار نرم‌افزار سفارشی کار می‌کند.

یادداشت‌های مرتبط

یادداشت‌های مرتبط

دسته‌بندی‌ها

خدمات مرتبط

از یادداشت تا پروژه

اگر موضوع این مقاله به سیستم یا محصول شما نزدیک است، می‌توانیم درباره دامنه واقعی صحبت کنیم.

اگر در انتخاب معماری یا مسیر توسعه مطمئن نیستید، می‌توانید درباره پروژه صحبت کنیم.

مسئله و محدودیت را بنویسید. اگر تطابق داشته باشیم، برای گفتگو هماهنگ می‌کنیم.

git merge چگونه کار می‌کند
fast-forward
merge commit
three-way merge
recursive strategy
octopus
سهیل ابراهیم‌پور
یادداشت‌ها
Monolith در برابر Microservices: کدام را انتخاب کنیم؟
Logging چیست؟ ثبت رویداد برای تشخیص و پاسخ به حادثه
Empty State، Error State و Loading State چیست؟
UX مهم‌تر است یا UI؟
چرا متن بد می‌تواند حتی یک UI زیبا را خراب کند؟

معماری نرم‌افزار

Monolith در برابر Microservices: کدام را انتخاب کنیم؟

۲۹ شهریور ۱۴۰۵

عملیات و استقرار

Logging چیست؟ ثبت رویداد برای تشخیص و پاسخ به حادثه

۲۹ شهریور ۱۴۰۵

مهندسی محصول

Empty State، Error State و Loading State چیست؟

۲۹ شهریور ۱۴۰۵

مهندسی محصول

UX مهم‌تر است یا UI؟

۲۹ شهریور ۱۴۰۵

مهندسی محصول

چرا متن بد می‌تواند حتی یک UI زیبا را خراب کند؟

۲۹ شهریور ۱۴۰۵
همه یادداشت‌ها219
معماری نرم‌افزار13
واژه‌نامه37
عملیات و استقرار87
مهندسی محصول74
راهنمای وب8
طراحی و ساخت محصول
توسعه فول‌استک
ممیزی مهندسی
مشاوره معماری
زیرساخت و استقرار
پروژه‌تان را مطرح کنید
ابزارهای رایگان
پروژه‌تان را مطرح کنید