تضمين Git في نظام تطوير المشاريع


نما المطورون الذين يعرفون ويعرفون كيفية العمل مع git بترتيب ضخم مؤخرًا. تعتاد على سرعة تنفيذ الأمر. تعتاد على راحة الفروع وسهولة التراجع عن التغييرات. حل النزاعات أمر شائع جدًا لدرجة أن المبرمجين يستخدمون لحل النزاعات بشكل بطولي حيث لا يجب أن يكونوا.


يعمل فريقنا في Directum على تطوير أداة تطوير لحلول الأنظمة الأساسية. إذا رأيت 1C ، فيمكنك أن تتخيل تقريبًا بيئة عمل "عملائنا" - مطوري التطبيقات. باستخدام أداة التطوير هذه ، يقوم مطور التطبيق بإنشاء حل تطبيق للعملاء.


واجه فريقنا مهمة تبسيط حياة المتقدمين لدينا. نحن مدللون بالرقائق الحديثة من Visual Studio و ReSharper و IDEA. طالب مقدمو الطلبات بدمج بوابة خارج الصندوق في الأداة.


هذه هي الصعوبة. في الأداة لكل نوع من الكيانات (العقد ، التقرير ، الدليل ، الوحدة النمطية) ، يمكن أن يكون هناك قفل. بدأ أحد المطورين بتحرير نوع الكيان وحظره حتى أكمل التغييرات وأرسلها إلى الخادم. يعرض المطورون الآخرون في الوقت الحالي نفس نوع الكيان للقراءة فقط. كان التطوير يذكرنا إلى حد ما بالعمل في SVN أو إرسال مستند Word عن طريق البريد بين عدة مستخدمين. أريد كل شيء دفعة واحدة ، ولكن ربما واحد فقط.


يمكن أن يكون لكل نوع من الكيانات العديد من المعالجات (فتح مستند ، التحقق من الصحة قبل الحفظ ، الكتابة إلى قاعدة البيانات) حيث تريد كتابة التعليمات البرمجية التي تعمل مع مثيل محدد من الكيان. على سبيل المثال ، قفل الأزرار ، أو عرض رسالة للمستخدم ، أو إنشاء مهمة جديدة لفناني الأداء. جميع التعليمات البرمجية في إطار API المقدمة من المنصة. المعالجات هي فئات تكمن فيها العديد من الطرق. عندما احتاج شخصان إلى إصلاح نفس الملف باستخدام الشفرة ، لم يكن من الممكن القيام بذلك ، لأن النظام الأساسي حظر نوع الكيان بالكامل مع الشفرة التابعة.


ذهب ممارسونا على طول الطريق. قاموا بتزوير أنفسهم بهدوء نسخة "غير قانونية" من بيئتنا التنموية ، وعلقوا على الجزء المحظور ، ودمجوا التزاماتنا لأنفسهم. تم الاحتفاظ بكود التطبيق تحت git ، تم الالتزام به من خلال أدوات الطرف الثالث (git bash و SourceTree وغيرها). لقد توصلنا إلى استنتاجاتنا:


  1. قلل فريقنا من تقدير مطوري التطبيقات للتوافق مع النظام الأساسي. احترام وشرف كبيرين!
  2. الحل الذي اقترحوه غير مناسب للإنتاج. باستخدام git ، تكون أيدي الشخص غير مربوطة وهو قادر على إنشاء أي شيء. لدعم كل التنوع سيكون من الغباء ، لا تخطف. بالإضافة إلى ذلك ، سيكون من الضروري تثقيف عملاء المنصة. إن توثيق جميع أوامر git للنظام الأساسي سيؤدي إلى جنون فريق التوثيق.


ماذا تريد من Git


لذا فإن التخلي عن الإنتاج باستخدام git out ليس جيدًا. قررنا بشكل أو بآخر تغليف منطق العمليات الرئيسية وتحديد عددها. على الأقل للإصدار الأول. تم تخفيض قائمة الفرق قدر الإمكان وبقيت:


  • الوضع
  • ارتكاب
  • سحب
  • دفع
  • إعادة تعيين --hard إلى HEAD
  • إعادة تعيين إلى آخر التزام "الخادم"

في الإصدار الأول ، قرروا رفض العمل مع الفروع. ليس هذا صعبًا للغاية ، فقط الفريق لم يلتق بمورد الوقت.


بشكل دوري ، يرسل شركاؤنا تطوير تطبيقاتهم ويسألون: "شيء ما لا يصلح لنا. ما الخطأ الذي نفعله؟". في هذه الحالة ، يقوم التطبيق بتحميل نفسه بتطوير شخص آخر وينظر إلى الرمز. كان هذا يعمل مثل هذا:


  1. أخذ المطور الأرشيف مع التطوير ؛
  2. تغيير قاعدة البيانات المحلية في التكوينات ؛
  3. سكب تطور شخص آخر إلى قاعدته ؛
  4. تصحيح الأخطاء وجدت.
  5. التوصيات الصادرة ؛
  6. عاد تطوره مرة أخرى.

المنهجية الجديدة لا تتناسب مع النهج القديم. كان علي تحطيم رأسي. اقترح الفريق نهجين لحل هذه المشكلة:


  1. قم بتخزين كل التطوير في مستودع git واحد. إذا لزم الأمر ، فاعمل مع قرار شخص آخر بإنشاء فرع مؤقت.
  2. متجر تطوير فرق مختلفة في مستودعات مختلفة. انقل إعدادات المجلدات المحملة في البيئة إلى ملف التكوين.

قررنا اتباع المسار الثاني. بدا الأول أكثر صعوبة في التنفيذ ، وعلاوة على ذلك ، كان من الأسهل إطلاق النار على قدمك من خلال تبديل الفروع.


ولكن الثاني ليس حلوًا أيضًا. يجب ألا تعمل الأوامر الموضحة أعلاه في نفس المستودع فقط ، ولكن مع عدة أوامر في وقت واحد. هل هناك تغيير في أنواع الكيانات من مستودعات مختلفة؟ نعرضها في نافذة واحدة. هذا أكثر ملاءمة وشفافية لمطور التطبيق. بالضغط على زر الالتزام ، تقوم الأداة بإجراء تغييرات على كل من المستودعات. وفقًا لذلك ، تعمل أوامر السحب / الدفع / إعادة التعيين "تحت غطاء المحرك" مع مستودعات مختلفة فعليًا.



Libgit2sharp


للعمل مع git ، اخترنا من خيارين:


  1. العمل مع git مثبت على النظام ، وسحبه من خلال العملية.بدء وتحليل الناتج.
  2. استخدم libgit2sharp ، والتي تسحب مكتبة libgit2 عبر pinvoke.

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


تكرار التطوير الأول


كان من الممكن تنفيذه في حوالي شهر. في الواقع ، كان شد البوابة سريعًا ، ومعظم الوقت حاولنا شفاء الجروح التي تم فتحها لأننا قطعنا الآلية القديمة لتخزين ملفات المصدر. تم إرجاع كل شيء تم إرجاعه إلى git status إلى الواجهة. النقر على كل ملف يعرض فرق. بدا وكأنه واجهة git gui.


تكرار التطوير الثاني


كان الخيار الأول غني بالمعلومات. مع كل نوع من الكيانات ، يتم ربط العديد من الملفات مرة واحدة. أحدثت هذه الملفات ضوضاء ، وأصبح من غير الواضح ما هي أنواع الكيانات التي تغيرت وماذا بالضبط.


الملفات المجمعة حسب نوع الكيان. تم إعطاء كل ملف اسمًا يمكن قراءته بواسطة الإنسان ، كما هو الحال في واجهة المستخدم الرسومية. تم وصف البيانات الوصفية لنوع الكيان في JSON. كما يجب تقديمها بتنسيق يمكن للمستخدم قراءته. تم بدء تحليل التغييرات في إصدارات json "قبل" و "بعد" باستخدام مكتبة jsondiffpatch ، ثم كتبوا التنفيذ الخاص بهم لمقارنة JSON (فيما يلي سوف أسمي jsondiff). ندير نتائج المقارنة من خلال المحللين الذين ينتجون سجلات قابلة للقراءة البشرية. تم إخفاء العديد من الملفات من العرض ، تاركًا إدخالًا بسيطًا في شجرة التغيير.


النتيجة النهائية هي كما يلي:



تواجه مشكلة مع libgit2


ولدت Libgit2 عددًا كبيرًا من المفاجآت غير المتوقعة. كان التعامل مع البعض خارج نطاق قوة وقت معقول. سأخبرك بما أتذكره.


يقع غير متوقع وصعب التكاثر يقع على بعض العمليات القياسية. يخبرنا الغلاف بأنه "لم يتم توفير أي خطأ بواسطة المكتبة الأصلية". عظيم. أنت تشتم ، فأنت تعيد بناء المكتبة الأصلية في تصحيح الأخطاء ، فأنت تكرر حالة تم إسقاطها مسبقًا ، ولكنها لا تتعطل في وضع التصحيح. إعادة البناء في الإصدار والسقوط مرة أخرى.


إذا كانت أداة تابعة لجهة خارجية ، مثل SourceTree ، تعمل بالتوازي مع libgit2sharp ، فقد لا يلزم تنفيذ بعض الملفات. أو يتجمد عند عرض يختلف على بعض الملفات. بمجرد محاولة تصحيح الأخطاء ، لا يمكنك التكاثر.


في أحد تطبيقاتنا ، استغرق تنفيذ تناظري git status 40 ثانية. فورتي كارل! في الوقت نفسه ، عملت البوابة التي تم إطلاقها من وحدة التحكم كما يجب أن تكون لثانية واحدة. قضيت بضعة أيام لترتيب الأمر. عند البحث عن التغييرات ، يبحث Libgit2 عن سمات الملف للمجلدات ويقارنها بالإدخال في الفهرس. إذا كان وقت التعديل مختلفًا ، فقد تغير شيء ما داخل المجلد وتحتاج إلى البحث داخله و / أو البحث في الملفات. وإذا لم يتغير شيء ، فلا يجب عليك الصعود إلى الداخل. يبدو أن هذا التحسين موجود أيضًا في بوابة وحدة التحكم. لا أعرف لأي سبب ، ولكن فقط لشخص واحد في git index gtime تغير. وبسبب هذا ، قام git بفحص محتويات جميع الملفات الموجودة في المستودع في كل مرة لمعرفة التغييرات.


أقرب إلى الإفراج ، استسلم فريقنا لرغبات فريق التطبيق واستبدل git pull بـ fetch + rebase + autostash . ثم جاءت إلينا مجموعة من الأخطاء ، بما في ذلك مع "لم يتم توفير خطأ من قبل المكتبة الأصلية".


تعمل الحالة والسحب وإعادة التمديد لفترة أطول بكثير من استدعاء أوامر وحدة التحكم.


دمج تلقائي


تنقسم الملفات قيد التطوير إلى نوعين:


  1. الملفات التي يراها التطبيق في أداة التطوير. على سبيل المثال ، رمز ، صور ، موارد. يجب دمج مثل هذه الملفات كما يفعل git.
  2. ملفات JSON التي تم إنشاؤها بواسطة بيئة التطوير ، ولكن مطور التطبيق يراها فقط في شكل واجهة المستخدم الرسومية. إنهم بحاجة إلى حل النزاعات تلقائيًا.
  3. الملفات التي تم إعادة إنشائها تلقائيًا عند العمل باستخدام أداة التطوير. لا تدخل هذه الملفات في المستودع ، وتضع الأداة بعناية .gitignore.

بطريقة جديدة ، تمكن تطبيقان مختلفان من تغيير نفس نوع الكيان.


على سبيل المثال ، ستقوم Sasha بتغيير المعلومات حول كيفية تخزين نوع الكيان في قاعدة البيانات وكتابة معالج للحدث المحفوظ ، وسيعمل Sergey على تصميم تمثيل الكيان. من وجهة نظر git ، لن يكون هذا تعارضًا ، وسيتم دمج كلا التغيرين دون تعقيد.


ثم قامت ساشا بتغيير خاصية Property1 وتعيين معالج لها. قام Sergey بإنشاء الخاصية Property2 وتعيين المعالج. إذا نظرت إلى الموقف من الأعلى ، فإن تضارباتهم لا تتعارض ، على الرغم من وجهة نظر git أن نفس الملفات تتأثر.
أردت أن تكون الأداة قادرة على حل هذا الوضع بمفردها.


مثال خوارزمية لدمج جزيئين JSON في حالة وجود تعارض:


  1. تنزيل من بوابة JSON الأساسية.


  2. قم بالتنزيل من JSON gita.


  3. تنزيل JSON الخاص بهم من بوابة.


  4. باستخدام jsondiff ، نشكل تصحيحات برامجنا الأساسية ونطبقها على حزمهم. يسمى JSON الناتج P1.


  5. باستخدام jsondiff ، نشكل تصحيحات برمجية خاصة بهم ونطبقها على برامجنا. يسمى JSON الناتج P2.


  6. من الناحية المثالية ، بعد تطبيق البقع P1 === P2. إذا كان الأمر كذلك ، فاكتب P1 إلى القرص.


  7. في حالة غير كاملة (عندما يكون هناك صراع بالفعل) ، نقترح على المستخدم الاختيار بين P1 و P2 مع القدرة على الانتهاء بيديه. نكتب التحديد إلى القرص.

بعد الدمج ، نتحقق مما إذا كانت الحالة بدون أخطاء في التحقق قد وصلت. إذا لم تكن قد وصلت ، فقم بإلغاء الدمج واطلب من المستخدم تكرارها. هذا ليس الحل الأفضل ، لكنه على الأقل يضمن أنه من المحاولة الثانية أو الثالثة ، سيحدث الاندماج دون عواقب غير سارة.


الملخص


  1. الجزارين سعداء لأنهم يمكنهم استخدامها بشكل قانوني.
  2. إدخال بوابة التنمية المتسارعة.
  3. تبدو عمليات الاندماج التلقائي مثل السحر بشكل عام.
  4. نرفض الرفض المستقبلي لـ libgit2 لصالح التذرع بعملية git.

Source: https://habr.com/ru/post/ar412787/


All Articles