انتقل إلى المحتوى الرئيسي انتقل إلى الملاحة انتقل إلى التذييل
لفترة محدودة: برنامج Design Partner — خطة BUSINESS مجانية مدى الحياة

rdc repo diff

عرض الفروقات بين مستودعَي نسخ-عند-الكتابة المتشعبَين على مستوى الملف بأسلوب git، من خلال مقارنة صورهما المشفرة على مستوى الكتل، دون الحاجة إلى فك التشفير.

rdc repo diff

يُبلّغ rdc repo diff عن الملفات التي تغيّرت بين مستودعَين مترابطَين: نسخة متشعبة وأصلها، أو أي مستودعَين يتشاركان سلفًا مشتركًا من نوع نسخ-عند-الكتابة. مرّر --name <fork> لمقارنة نسخة متشعبة مع أصلها المسجَّل في الإعداد المحلي، أو أضف --base <repo> للمقارنة مع أي مستودع مترابط آخر، حيث يُمثّل --base الجانب الأساسي (القديم) ويُمثّل --name الجانب الهدف (الجديد). الأمر للقراءة فقط ولا يفك تشفير الصور قط. يُجري المقارنة على مستوى الكتل في الجهاز البعيد، لذا تتناسب التكلفة مع عدد الكتل المتغيّرة لا مع حجم المستودع: مستودع بحجم 1 GB ومستودع بحجم 100 GB يستغرقان الوقت ذاته طالما أن التعديلات متماثلة. إذا تغيّر المستودع بالكامل، فإن عدد الكتل يتناسب مع الحجم وتتناسب التكلفة معه بالتبعية.

متى تستخدمها

الخلاصة: الجأ إلى repo diff قبل ترقية أي نسخة متشعبة. إذا شغّل وكيل ذكاء اصطناعي بحرية داخل نسخة متشعبة من بيئة الإنتاج وأردت معرفة الملفات التي لمسها تحديدًا قبل دمج التغيير: يمنحك repo diff --name <fork> -m <machine> قائمة الملفات في ثوانٍ. ثوانٍ. بعد استعادة الكوارث، قارن النسخة المستعادة باللقطة التي كان من المفترض أن تُعيد إنتاجها للتأكد من عودة مجموعة الملفات المتوقعة دون أي انحراف. أما النسخة المتشعبة طويلة الأمد التي عملت جنبًا إلى جنب مع أصلها لأسابيع، فإن الفرق يُظهر التباين المتراكم (تعديلات الإعداد، تراكم السجلات، ترحيل المخطط) دون الحاجة إلى تحميل الشجرتين وتصفحهما يدويًا.

لا تستخدم هذه الأداة بين مستودعات غير مترابطة. يجب أن يتشارك الطرفان سلفًا مشتركًا من نوع نسخ-عند-الكتابة، لأن المقارنة تعتمد على تاريخ الكتل المشترك. كما أنها ليست أداة مقارنة ثنائية: يُنتج --content مخرجات على مستوى السطر للملفات النصية فقط، وتُبلّغ الملفات الثنائية بـ Binary files differ.

مرجع الأوامر

الصيغة العامة

rdc repo diff --name <fork> -m <machine>            # diff a fork against its parent
rdc repo diff --name <fork> --base <repo> -m <machine>   # diff against an arbitrary related repo

الخيارات

الخيارالوصفالافتراضي
--name <name>المستودع المراد فحصه (الجانب الهدف، الجديد). مطلوب.مطلوب
--base <name>المستودع المراد المقارنة معه (الجانب الأساسي، القديم). يُعيّن افتراضيًا إلى أصل --name المحلول من الإعداد المحلي.أصل --name
(بدون علامة تنسيق)مخرجات الاسم والحالة: حرف ملوّن A/M/D/R لكل ملف متغيّر مع سطر ملخص.مفعّل
--name-onlyمسار واحد لكل سطر دون حرف الحالة. مناسب للتمرير عبر الأنابيب.معطّل
--statحجم التغيير لكل ملف (دلتا البايتات والكتل) مع تذييل يحتوي الإجماليات.معطّل
--content <path>فرق نصي موحّد لملف نصي واحد. للنصوص فقط؛ تُبلّغ الملفات الثنائية بـ Binary files differ.معطّل
--jsonمخرجات منظّمة للوكلاء والسكريبتات.معطّل
--fastتخطي خطوة تأكيد تجزئة المحتوى والوثوق بفلتر الكتل. أسرع، لكنه قد يُبالغ في الإبلاغ عن ملفات على أنها معدّلة.معطّل
-m, --machine <name>الجهاز الهدف. مطلوب.مطلوب
--debugتشخيصات مفصّلة على stderr.معطّل
--skip-router-restartتخطي خطوة إعادة تشغيل الموجّه.معطّل

أمثلة

مقارنة الاسم والحالة الافتراضية مع الأصل

عند تمرير --name فقط، تُقارَن النسخة المتشعبة مع الأصل المسجّل في الإعداد المحلي. في المثال التالي، النسخة المتشعبة test-1gb:fork1 تحتوي على ملف واحد معدَّل:

$ rdc repo diff --name test-1gb:fork1 -m hostinger
M  hello.txt

1 file changed: 0 added, 1 modified, 0 deleted, 0 renamed

المقارنة مع قاعدة محددة

مرّر --base للمقارنة مع أي مستودع مترابط. --base هو الجانب الأساسي (القديم)، و--name هو الجانب الهدف (الجديد):

$ rdc repo diff --name test-1gb:fork1 --base test-1gb:latest -m hostinger
M  hello.txt

1 file changed: 0 added, 1 modified, 0 deleted, 0 renamed

حجم التغيير مع --stat

يُضيف --stat دلتا البايتات والكتل لكل ملف مع تذييل يحتوي الإجماليات:

$ rdc repo diff --name test-1gb:fork1 --stat -m hostinger
 hello.txt | +8 bytes, 1 block

1 file changed, 4096 bytes touched

المسارات فقط، ممررة إلى أداة

يطبع --name-only مسارًا واحدًا في كل سطر دون حرف الحالة، جاهزًا للتمرير إلى أمر آخر:

$ rdc repo diff --name test-1gb:fork1 --name-only -m hostinger | xargs -I{} echo "review: {}"
review: hello.txt

فرق على مستوى السطر لملف واحد

يُنتج --content فرقًا موحدًا لملف نصي واحد:

$ rdc repo diff --name test-1gb:fork1 --content hello.txt -m hostinger
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-the original line of text in the parent
+the original line of text in the parent, now edited

تصفية JSON باستخدام jq

يُرسل --json الغلاف المنظّم إلى stdout، مما يجعله مناسبًا للتمرير مباشرةً إلى jq:

$ rdc repo diff --name test-1gb:fork1 --json -m hostinger | jq '.data.entries[] | select(.status=="M")'
{
  "status": "M",
  "path": "/hello.txt",
  "type": "file",
  "old_size": 53,
  "size": 61,
  "bytes_changed": 4096,
  "blocks_changed": 1,
  "inode": 13,
  "content_changed": true,
  "mode_changed": false,
  "uid_changed": false,
  "gid_changed": false
}

صيغ الإخراج

الاسم والحالة (الافتراضي)

يحصل كل ملف متغيّر على حرف حالة ومساره. A يعني مضاف، M معدَّل، D محذوف، R مُعاد تسمية (مع عرض المسار القديم). يلي ذلك سطر ملخص يحتوي العدد لكل فئة.

--name-only

مسار واحد في كل سطر، بدون حرف حالة ولا ملخص. استخدمه حين يحتاج الأمر اللاحق قائمة ملفات نظيفة.

--stat

يحمل كل سطر دلتا البايتات ودلتا الكتل للملف. يُبلّغ التذييل عن إجمالي عدد الملفات وإجمالي البايتات التي طالها التغيير. يُظهر هذا أين يتمركز ثقل التغيير، لا الملفات التي تأثرت فحسب.

--content <path>

فرق موحّد قياسي (رأسا ---/+++ وفقرات @@) لملف نصي واحد. تُبلّغ الملفات الثنائية بـ Binary files differ دون إنتاج أي فقرات.

--json

النتيجة المنظّمة الكاملة. تذهب البيانات إلى stdout وتذهب التقدّم والتشخيصات إلى stderr، مما يتيح تمرير JSON بشكل نظيف إلى jq أو أي محلّل آخر حتى أثناء طباعة مؤشرات التقدّم.

مخطط JSON

يُغلّف CLI نتيجة renet في الغلاف القياسي (success، command، data، errors، warnings، metrics). تقع نتيجة الفرق داخل data بحقول بصيغة snake_case:

{
  "success": true,
  "command": "repo diff",
  "data": {
    "base": "<base-guid>",
    "target": "<target-guid>",
    "added": 0,
    "modified": 1,
    "deleted": 0,
    "renamed": 0,
    "strategy": "shared",
    "fast": false,
    "degraded": false,
    "block_size": 4096,
    "total_bytes_changed": 4096,
    "entries": [
      {
        "status": "M",
        "path": "/hello.txt",
        "type": "file",
        "old_size": 53,
        "size": 61,
        "bytes_changed": 4096,
        "blocks_changed": 1,
        "inode": 13,
        "content_changed": true,
        "mode_changed": false,
        "uid_changed": false,
        "gid_changed": false
      }
    ]
  }
}

كل كائن في entries[] يصف مسارًا واحدًا متغيّرًا:

الحقلالنوعالوصف
statusA | M | D | Rمضاف أو معدَّل أو محذوف أو مُعاد تسمية.
pathstringالمسار على الجانب الهدف (أو الجانب الأساسي عند الحذف).
old_pathstringالمسار السابق. موجود عند إعادة التسمية فقط.
typefile | dir | symlink | otherنوع المدخلة.
old_sizenumberالحجم بالبايت على الجانب الأساسي.
sizenumberالحجم بالبايت على الجانب الهدف.
bytes_changednumberالبايتات المختلفة، مقرَّبة للأعلى إلى كتل كاملة.
blocks_changednumberعدد الكتل المتغيّرة.
inodenumberرقم inode، يُستخدم لاكتشاف إعادة التسمية.
content_changedbooleanما إذا تغيّر محتوى الملف (لا البيانات الوصفية فقط).
mode_changedbooleanما إذا تغيّر وضع الملف. يظهر old_mode/new_mode عندما تكون القيمة true.
uid_changedbooleanما إذا تغيّر المالك. يظهر old_uid/new_uid عندما تكون القيمة true.
gid_changedbooleanما إذا تغيّرت المجموعة. يظهر old_gid/new_gid عندما تكون القيمة true.
old_target / new_targetstringوجهات الروابط الرمزية. موجودة للروابط الرمزية المتغيّرة.

لحقول الغلاف وقواعد الاكتشاف التلقائي التي تُصدر JSON في البيئات غير الطرفية، راجع مرجع مخرجات JSON.

آلية العمل

المستودع عبارة عن ملف صورة LUKS2 على مجموعة btrfs، والنسخة المتشعبة هي reflink ثابت الوقت لتلك الصورة. يقارن repo diff الصورتَين المشفَّرتَين على مستوى الكتل عبر FIEMAP، يقرأ البيانات الوصفية لنظام الملفات فقط دون فك تشفير أي شيء. يُحوّل إزاحات النص المشفّر المتغيّرة بإزاحة بيانات LUKS للحصول على إزاحات جهاز ext4، ثم يُعيد ربط تلك الإزاحات بأسماء الملفات عبر خريطة الامتدادات ext4 لكل ملف. يُتبع ذلك بجولة تعريف inode على كلتا التحميلتين تُوفّق النتيجة في مدخلات مضافة ومعدَّلة ومحذوفة ومُعادة التسمية. نظرًا لأن العمل محدود بعدد الكتل المتغيّرة، يستقل الفرق عن حجم المستودع، ولأنه يُعيد استخدام تحميل قائم في مكانه، لا يُزعزع استقرار أي مستودع قيد التشغيل. الآلية الكاملة موصوفة في Git diff for encrypted disk images.

القيود

  • النسخ المتشعبة المترابطة فقط. يجب أن يتشارك الطرفان سلفًا مشتركًا من نوع نسخ-عند-الكتابة. لا توجد مقارنة ذات معنى على مستوى الكتل بين مستودعات غير مترابطة.
  • اكتشاف إعادة التسمية يعتمد على inode. يُبلَّغ عن ملف بوصفه مُعادًا تسميته حين يظهر inode ذاته في مسار جديد. الحذف ثم إعادة الإنشاء (inode جديد) يظهر كمدخلة محذوفة ومدخلة مضافة، لا كإعادة تسمية.
  • --content للنصوص فقط. يُنتج فقرات على مستوى السطر للملفات النصية. تُبلّغ الملفات الثنائية بـ Binary files differ.
  • قد يُبالغ --fast في الإبلاغ عن التعديلات. يثق بفلتر الكتل ويتخطى تأكيد تجزئة المحتوى، لذا قد يظهر ملف انتقلت كتله دون تغيير محتواه على أنه معدَّل.
  • وقت جولة الامتدادات يتناسب مع التجزئة لا مع الحجم. نظام الملفات المُجزَّأ بشدة يحتوي على امتدادات أكثر للتعيين، مما يُطيل الجولة حتى حين يكون حجم التغييرات بالبايت صغيرًا.

انظر أيضًا

  • rdc repo fork. إنشاء النسخة المتشعبة بنسخ-عند-الكتابة التي يقارنها هذا الأمر.
  • rdc repo status. الحالة الراهنة لمستودع واحد.
  • rdc repo cat. قراءة ملف واحد من مستودع.