گیج‌کننده‌های گیت: داستان عجایب Diff و Merge که فکرش رو هم نمی‌کنی!

Fall Back

اگه تا حالا با کدنویسی تو تیم سروکار داشتی یا پروژه‌ای رو تو گیت‌هاب پیش بردی، قطعاً اسم Git به گوشت خورده. Git همون سیستم کنترلیه که کد رو باهاش مدیریت می‌کنیم و کار گروهی رو خیلی راحت‌تر می‌کنه. اما جالبه بدونی با اینکه هر روز داریم ازش استفاده می‌کنیم، خیلیا دقیق نمی‌دونن پشت صحنش چه خبره، مخصوصاً وقتی می‌خوای diff و merge کنی.

حالا Diff و Merge چی هستن؟
آقا به زبان ساده، Diff اون چیزیه که بهت میگه چه تغییری تو کد دادی. مثلاً اگه یه خط کد پاک کنی یا اضافه کنی، این الگوریتم دقیق درمیاره که چی عوض شده. Merge هم وظیفه داره وقتی چند نفر همزمان تو یه پروژه تغییر دادن، این تغییراتو به صورت درست و سالم قاطی کنه – یعنی بشه یه نسخه نهایی بی‌مشکل.

حالا قضیه اینه که فرق نمی‌کنه چقدر Git استفاده کردی، بازم رفتار دقیق این الگوریتم‌ها عجیب و گاهی «غیر قابل پیش‌بینی» درمیاد!

الگوریتم Diff: یه اشتباه کوچیک، یه جهنم بزرگ!
Git چند جور الگوریتم برای Diff داره. مثلاً یکی به اسم Histogram diff (هیستوگرام دیف یعنی یه مدل خاص برای مقایسه خطوط فایل‌ها) و این یکی بعضی وقتا خیلی قاطی می‌کنه. مثلاً فقط یه خط کوچیک رو عوض کنی، یهو الگوریتم کل بقیه فایل رو به عنوان تغییرشمار درمیاره! یعنی مثلاً فقط یه ‘;’ رو برداری، بعد تو git diff کل فایل به هم میریزه. منطقی نیست دیگه، نه؟ ولی واقعاً همینطوره.

Merge و دردسر زمان: چرا بعضی مرج‌ها ساعت‌ها طول می‌کشه؟
می‌دونی تو Git یه حالتی هست که استراتژی ort یا همون حالت پیشفرض مرج (استراتژی یعنی روشی که Git برای قاطی کردن تغییرات استفاده می‌کنه) می‌تونه وقتی تعداد کمیت‌ها (commit – همون ذخیره‌سازی یا نقطه‌عطف تو تاریخچه پروژه) زیاد میشه، به صورت نمایی (یعنی وحشیانه سریع!) زمان لازم برای مرج کردنش زیاد بشه. خلاصه اگه پروژه سنگین باشه و کلی آدم روش کار کرده باشن، گاهی یه مرج می‌تونه صبر ایوب رو درت بیاره!

یه نکته باحال‌تر: Merge و Rebase همیشه اون‌جوری که فکر می‌کنی پیش نمیره!
ببین، Merge و Rebase (ری‌بیس یعنی اینکه تاریخچه کامیت‌ها رو جوری مرتب کنی که انگار تغییراتت مستقیماً بعد از تغییرات شاخه اصلی اضافه شده) اصلاً خاصیت جابجایی (Commutative) ندارن؛ یعنی اگه مثلاً اول A رو با B مرج کنی با اینکه اول B رو با A مرج کنی، ممکنه خروجی‌ها فرق کنه. عجیب‌تر اینکه حتی بعضی وقتا که مرج اصلاً هیچ کانفلیکتی (یعنی دعوای دو نفر سر یه خط خاص) نداره، بازم نتیجه بستگی به نوع الگوریتم Diff داره و مشخص نیست چی درمیاد!

وقتی دو نفر همزمان تو یه جا اضافه می‌کنن چی میشه؟
یه نکته جالب دیگه اینکه اگه دو نفر هرکدوم تو یه جای مشابه خط جدیدی اضافه کنن، Git همیشه سر اون خط گیر نمی‌کنه یا کانفلیکت نمیده؛ گاهی با خونسردی تمام هردو خط رو پشت سر هم می‌ذاره – اول خط A بعد خط B یا برعکس – و اینکه کدوم قبل درمیاد هم دیگه بستگی به مرام الگوریتم داره! یعنی نتیجه قشنگ قابل پیش‌بینی نیست.

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

پیشنهاد: اگه دوست داری درباره رفتار دقیق الگوریتم‌های پشت صحنه Git بیشتر بدونی، مقاله arXiv:2507.22071 رو یه نگاه بنداز. هم بامزه‌ست هم کلی نکته‌ی عجیب و غریب داره!

منبع: +