| GIT-RANGE-DIFF(1) | Git Manual | GIT-RANGE-DIFF(1) |
نام (NAME)
git-range-diff - مقایسه دو بازه کامیت (مثلاً دو نسخه از یک شاخه)
خلاصه دستور (SYNOPSIS)
git range-diff [--color=[<when>]] [--no-color] [<diff-options>]
[--no-dual-color] [--creation-factor=<factor>]
[--left-only | --right-only] [--diff-merges=<format>]
[--remerge-diff] [--no-notes | --notes[=<ref>]]
( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
[[--] <path>...]
توضیحات (DESCRIPTION)
این دستور تفاوتهای میان دو نسخه از یک مجموعه پچ (patch series)، یا به طور کلیتر، دو بازه کامیت را (با نادیده گرفتن کامیتهای ادغام یا merge) نمایش میدهد.
در صورت ارائه آرگومانهای <path>، این بازههای کامیت متناسب با آنها محدود میشوند.
برای این منظور، ابتدا جفت کامیتهایی را از هر دو بازه کامیت پیدا میکند که متناظر با یکدیگرند. دو کامیت زمانی متناظر در نظر گرفته میشوند که diff میان پچهای آنها (یعنی اطلاعات نویسنده، پیام کامیت و diff کامیت) در مقایسه با اندازه پچها به اندازه کافی کوچک باشد. برای جزئیات به بخش الگوریتم (Algorithm) در ادامه مراجعه کنید.
در نهایت، فهرست کامیتهای منطبق به ترتیب بازه کامیت دوم نشان داده میشود، در حالی که کامیتهای نامنطبق درست پس از نمایش همه نیاکان (ancestors) خود درج میگردند.
سه روش برای تعیین بازههای کامیت وجود دارد:
گزینهها (OPTIONS)
--no-dual-color
علاوه بر این، خطوط diff کامیت که فقط در اولین بازه کامیت وجود دارند به صورت «کمرنگ» (dimmed) نشان داده میشوند (این رفتار را میتوان با استفاده از تنظیم پیکربندی color.diff.<slot> تغییر داد که در آن <slot> یکی از مقادیر contextDimmed، oldDimmed و newDimmed است)، و خطوط diff کامیت که فقط در بازه کامیت دوم حضور دارند به صورت پررنگ (bold) نمایش مییابند (که با تنظیمات پیکربندی color.diff.<slot> با <slot> برابر با یکی از contextBold، oldBold یا newBold قابل سفارشیسازی است).
این قابلیت در range-diff به عنوان «رنگآمیزی دوگانه» (dual coloring) شناخته میشود. از --no-dual-color استفاده کنید تا رنگآمیزی تمام خطوط بر اساس نشانگرهای diff بیرونی انجام شود (و diff درونی از نظر رنگ کاملاً نادیده گرفته شود).
--creation-factor=<percent>
--left-only
--right-only
--diff-merges=<format>
نکته: در حالت معمول، حالت remerge طبیعیترین حالت برای استفاده خواهد بود، زیرا فقط diff را روی خروجی حاصل از مکانیزم ادغام گیت نشان میدهد. به عبارت دیگر، اگر یک کامیت ادغام نتیجه یک git merge بدون تداخل باشد، حالت remerge آن را با یک diff خالی نمایش خواهد داد.
--remerge-diff
--notes[=<ref>], --no-notes
<range1> <range2>
<rev1>...<rev2>
<base> <rev1> <rev2>
دستور git range-diff همچنین گزینههای معمولی diff را میپذیرد (به git-diff(1) مراجعه کنید)، بهویژه گزینههای --color[=<when>] و --no-color. این گزینهها هنگام تولید «diff میان پچها» استفاده میشوند، یعنی برای مقایسه نویسنده، پیام کامیت و diff کامیتهای متناظر قدیم/جدید. در حال حاضر روشی برای دستکاری بیشتر گزینههای diff ارسالشده به git log هنگام تولید این پچها وجود ندارد.
پایداری خروجی (OUTPUT STABILITY)
خروجی دستور range-diff ممکن است تغییر کند. این خروجی برای خوانایی توسط انسان طراحی شده است (خروجی پرسلین یا porcelain)، نه چیزی که بتوان در نسخههای مختلف گیت برای دستیابی به یک range-diff متنی پایدار استفاده کرد (برخلاف گزینهای مانند --stable در git-patch-id(1)). همچنین هیچ معادلی برای git-apply(1) در range-diff وجود ندارد؛ خروجی این دستور برای ماشینخوان بودن در نظر گرفته نشده است.
این موضوع به ویژه هنگام ارسال گزینههای diff صادق است. در حال حاضر برخی گزینهها مانند --stat میتوانند اثر جانبی داشته باشند و خروجیای تولید کنند که در زمینه range-diff کاملاً بیفایده است. ممکن است نسخههای آینده range-diff نحوه تفسیر این گزینهها را به روشی ویژه range-diff یاد بگیرند (برای مثال برای --stat خروجی خوانا برای انسان تولید کنند که نحوه تغییر diffstat را خلاصه کند).
پیکربندی (CONFIGURATION)
این دستور از تنظیمات diff.color.* و pager.range-diff استفاده میکند (مورد دوم به طور پیشفرض فعال است). به git-config(1) مراجعه کنید.
مثالها (EXAMPLES)
هنگامی که یک ریبیس نیازمند حل تداخلهای ادغام بود، بلافاصله پس از آن تغییرات ایجادشده توسط ریبیس را با دستور زیر مقایسه کنید:
$ git range-diff @{u} @{1} @
یک خروجی نمونه از git range-diff به این صورت خواهد بود:
-: ------- > 1: 0ddba11 Prepare for the inevitable!
1: c0debee = 2: cab005e Add a helpful message at the start
2: f00dbal ! 3: decafe1 Describe a bug
@@ -1,3 +1,3 @@
Author: A U Thor <author@example.com>
-TODO: Describe a bug
+Describe a bug
@@ -324,5 +324,6
This is expected.
-+What is unexpected is that it will also crash.
++Unexpectedly, it also crashes. This is a bug, and the jury is
++still out there how to fix it best. See ticket #314 for details.
Contact
3: bedead < -: ------- TO-UNDO
در این مثال، ۳ کامیت قدیمی و ۳ کامیت جدید وجود دارد، که در آن توسعهدهنده کامیت سوم را حذف کرده، یک کامیت جدید قبل از دو کامیت اول اضافه کرده، و پیام کامیت دوم و همچنین diff آن را ویرایش کرده است.
هنگامی که خروجی به یک ترمینال ارسال میشود، به طور پیشفرض رنگبندی میشود، درست مانند خروجی معمول git diff. علاوه بر این، خط اول (افزودن یک کامیت) سبز است، خط آخر (حذف یک کامیت) قرمز است، خط دوم (با تطابق کامل) مانند هدر کامیت در خروجی git show زرد است، و خط سوم کامیت قدیمی را قرمز، کامیت جدید را سبز و بقیه را مانند هدر کامیت git show رنگآمیزی میکند.
با این حال، یک diff ساده از diffها که با رنگ تفکیک شده باشد، خواندنش کمی دشوار است، زیرا کل خطوط را قرمز یا سبز میکند. به عنوان مثال، خطی که "+What is unexpected" را در کامیت قدیمی اضافه کرده بود کاملاً قرمز است، حتی اگر هدف کامیت قدیمی اضافه کردن چیزی بوده باشد.
برای حل این مشکل، دستور range-diff به طور پیشفرض از حالت --dual-color استفاده میکند. در این حالت، diff از diffها رنگهای اصلی diff را حفظ کرده و خطوط را با نشانگرهای -/+ که دارای پسزمینه قرمز یا سبز هستند پیشوندگذاری میکند تا واضحتر شود که آنها چگونگی تغییر خود diff را توصیف میکنند.
الگوریتم (ALGORITHM)
ایده کلی به این صورت است: یک ماتریس هزینه بین کامیتهای هر دو بازه کامیت تولید میکنیم، سپس مسئله تخصیص کمترین هزینه (least-cost assignment) را حل میکنیم.
ماتریس هزینه به این شیوه مقداردهی میشود: برای هر جفت کامیت، هر دو diff تولید میشوند و سپس «diff از diffها» با ۳ خط بافت (context) ایجاد میشود، سپس تعداد خطوط موجود در آن diff به عنوان هزینه در نظر گرفته میشود.
برای جلوگیری از مثبتهای کاذب (false positives - مثلاً هنگامی که یک پچ حذف شده و پچ نامرتبط دیگری بین دو تکرار از همان مجموعه پچ اضافه شده است)، ماتریس هزینه با افزودن ورودیهای دارای هزینه ثابت برای حذفها/افزودنهای کلی گسترش مییابد.
مثال: فرض کنید کامیتهای 1--2 اولین تکرار از یک مجموعه پچ و A--C دومین تکرار باشند. فرض کنیم A یک cherry-pick از 2 باشد، و C یک cherry-pick از 1 ولی با تغییری کوچک (مثلاً رفع یک اشتباه تایپی). کامیتها را به صورت یک گراف دوبخشی تجسم کنید:
1 A
2 B
C
ما به دنبال «بهترین» توضیح برای مجموعه جدید بر حسب مجموعه قدیمی هستیم. میتوانیم یک «توضیح» را به صورت یک یال در گراف نشان دهیم:
1 A
/
2 --------' B
C
این توضیح «رایگان» (بدون هزینه) تمام میشود چون هیچ تغییری وجود نداشته است. به طور مشابه C میتواند با استفاده از 1 توضیح داده شود، اما این کار به دلیل وجود تغییر با مقداری هزینه c>0 همراه است:
1 ----. A
| /
2 ----+---' B
|
`----- C
c>0
از نظر ریاضی، آنچه به دنبال آن هستیم نوعی تطابق دوبخشی با کمترین هزینه است؛ ‘1` با مقداری هزینه با C منطبق میشود، و الی آخر. گراف زیربنایی در واقع یک گراف دوبخشی کامل است؛ هزینهای که به هر یال نسبت میدهیم اندازه diff میان پچهای دو کامیت است. برای توضیح کامیتهای جدید نیز گرههای ساختگی (dummy nodes) را در هر دو طرف معرفی میکنیم:
1 ----. A
| /
2 ----+---' B
|
o `----- C
c>0
o o
o o
هزینه یک یال o--C اندازه diff کامیت C است که با یک ضریب تعدیل (fudge factor) که باید کمتر از ۱۰۰٪ باشد اصلاح میشود. هزینه یک یال o--o رایگان (صفر) است. این ضریب تعدیل ضروری است زیرا حتی اگر 1 و C هیچ اشتراکی نداشته باشند، ممکن است هنوز چند خط خالی و موارد مشابه را به اشتراک بگذارند، و احتمالاً تخصیص 1--C, o--o را کمی ارزانتر از 1--o, o--C کند، حتی اگر 1 و C هیچ وجه اشتراکی نداشته باشند. با ضریب تعدیل ما بخش مشترک بسیار بزرگتری را برای متناظر دانستن پچها نیاز داریم.
کل زمان مورد نیاز برای محاسبه این الگوریتم، زمان لازم برای محاسبه n+m دیف کامیت و سپس n*m دیف پچها است، به علاوه زمان لازم برای محاسبه کمهزینهترین تخصیص بین n و m دیف. گیت از پیادهسازی الگوریتم یانکر-ولگنانت (Jonker-Volgenant) برای حل مسئله تخصیص استفاده میکند که دارای پیچیدگی زمانی مکعبی (cubic) است. تطابق یافتشده در این حالت به این شکل خواهد بود:
1 ----. A
| /
2 ----+---' B
.--+-----'
o -' `----- C
c>0
o ---------- o
o ---------- o
همچنین ببینید (SEE ALSO)
گیت (GIT)
بخشی از مجموعه git(1)
| 2026-06-29 | Git 2.55.0 |