في المقال السابق، تحدّثت عن بعض أهمّ الأدوات التي ستحتاج إلى استخدامها عند العمل على مشاريع Data Science بما فيها widgets الخاصّة بـ Git في VS Code. في هذا المقال، سنُزيل الغموض عن أداة Git التي تسمح بـ versioning للشيفرة الخاصة بك إلى جانب التعامل مع المستودعات collaborative.
الملخّص كالتالي:
- Git وGitHub/GitLab
- أوّل مستودع لك
- دفع الشيفرة وسحبها
- فلسفة مشاريع Git
- CI-CD مع GitLab
Git وGithub
Git أداة برمجية تُستخدم بشكل أساسي لثلاثة أسباب:
- إصدار الشيفرة بمرور الوقت
- تتبّع التغييرات المُجراة
- السماح بالتعاون المتوازي بين عدّة أطراف
للقيام بذلك، يعمل git على ثلاث مراحل:
Working directory: هو المجلّد المحلّي الذي يستضيف جميع ملفّات مشروعك، وبشكل أدقّ، هو المجلّد الذي تمّت تهيئة git فيهStaging directory: يُدوّن ويُفهرس كلّ مستند معدَّلGit local repository: يؤدّي كلّ تغيير مُجرى إلى نسخة من المستند أو snapshot يمكن أخذه وتسميته باستخدام رسالة.
قبل التعمّق في أسطر أوامر git، لنرَ أوّلًا كيفية تثبيته وضبطه.
تثبيت Git
- Windows: حمّل مُثبِّت Git لنظام Windows من الموقع التالي
- Mac: معظم إصدارات MacOs لديها git مُثبَّت مسبقًا.
ضبط Git
كما ذُكر سابقًا، git أداة versioning وتعاون، ومن ثمّ من المهمّ معرفة الأشخاص الذين يعملون على كلّ ملفّ من ملفّات المشروع، ولهذا السبب يجب عليك ضبط git باستخدام اسمك وبريدك الإلكتروني:
git config --global user.name "Name"
git config --global user.mail "mail"
أوّل مستودع لك
إنشاء أوّل مستودع Git
بمجرّد تثبيت git وضبطه، يمكنك إنشاء أوّل مشروع git باستخدام أسطر الأوامر التالية:
mkdir projectFolder
cd projectFolder
git init #initialize git on your project
git status
touch file.md # create new file
open file.md # open the file and modify it
git status # file untracked -> add it to git index
git add file.md
git commit -m "file.md modified ..."في الفقرة التالية، ستجد الرسم البياني الذي يلخّص العلاقات بين المراحل المختلفة.
استضافة مستودعك على GitHub/GitLab
Github أو GitLab منصّتان تتيحان استضافة مشروعك وتنسيق التعاون متعدّد الأطراف. توضّح الخطوات التالية كيف يمكنك القيام بذلك:
- أنشئ حسابًا في GitHub/GitLab
- أنشئ Repository جديدًا
- انسخ رابطه
- استنسخه في مجلّد على جهازك
- قم بجميع التغييرات اللازمة المُسنَدة إلى الـ commits الخاصة بها
- ادفع التغييرات إلى GitHub/GitLab
ملاحظة 1: الخطوات الأربع الأولى تتمّ مرّة واحدة فقط، بينما الخامسة والسادسة تكراريّتان (انظر الفقرة التالية). ملاحظة 2: من الممكن أيضًا دفع مجلّد قائم إلى دليل github باستخدام:
git remote add origin gitAdress git branch -M master git push -u origin master
دفع الشيفرة وسحبها
بمجرّد إجراء جميع التغييرات، ستريد مشاركة عملك مع مستودع GitHub/GitLab لجعله متاحًا للأعضاء الآخرين في فريقك. فيما يلي الخطوات اللازم اتّباعها:
- عدّل الملفّ على جهازك
- شغّل:
git add file.extension #Add it to the git index:
git commit -m "message" #Commit the changes
git push #Push the changes to githubستحتاج أيضًا إلى الحصول على أحدث التغييرات التي قام بها الآخرون باستخدام سطر الأوامر التالي:
git pullيمثّل الرسم البياني التالي الصلة بين المستودع المحلّي ومستودع GitHub/GitLab.

ملاحظة: عند الدفع أو السحب من GitHub/GitLab يجب إدخال بيانات اعتمادك.
توضيح
في GIF التالي، سأنشئ مجلّدًا محلّيًا أُطلق فيه versioning بواسطة git وأنشئ أيضًا ملفًّا يُسمّى README.md ثمّ أُضيف التغييرات وأُجري commit. لاحقًا، سأنشئ Github repo سأدفع إليه المجلّد المحلّي وأتحقّق من أنّ Github تمّ تحديثه:

التعاون
عند العمل على مشروع معقّد، يُسنَد عادةً لكلّ عضو من الفريق مهمّة أو ميزة يمكنه العمل عليها بشكل مستقلّ. ومع ذلك، يمكن النظر إلى كلّ مشروع باعتباره عدّة مشاريع فرعية يديرها أعضاء مختلفون.
لتنسيق عملهم، يستخدم git مفهوم branches: الفرع الرئيسي يُسمّى master ويمكن دمج فروع أخرى فيه بمجرّد استقرار العمل عليها. يمكن استخدام branches أيضًا لفصل النسخة production عن نسخة development التي تُطوَّر فيها ميزات جديدة باستمرار، ومن هنا التسمية. إليك سير عمل ذكي للجمع بين الاثنين:

للقيام بذلك، يمكنك استخدام سكربت bash التالي، بمجرّد أن تكون في مستودع git:
git branch # get current branch (master)
git checkout -b devBranch # create and switch to development branch
git checkout -b featureBranch devBranch # Create feature branch over the development branch
git add file.extension # Add changed file to staging
git commit -m "message" # commit the message
git checkout devBranch # switch back to development branch
git merge featureBranch # merge featureBranch into devBranch
git push origin featureBranch # push the changes on featureBranch to github/gitlab
git push origin devBranch # push the changes on devBranch to github/gitlabهذا توضيح للتفرّع والدمج باستخدام المشروع السابق:

عند دمج فروع، قد تحدث بعض التعارضات، خصوصًا عندما يكون شخصان قد عملا على نفس الملفّ، في هذه الحالة، ينبغي عليك
- فتح الملفّ المُسبّب للتعارضات
- حلّ التعارضات (استخدم VSCode مثلًا)
- تشغيل:
git add .git commit -m "message"ملاحظة 1: يمكن النظر إلى branches أيضًا على أنّها وسيلة للمساهمة في مشاريع مفتوحة المصدر، أي تلك التي شيفرتها منشورة علنًا على GitHub/GitLab.
ملاحظة 2: قد ترغب في إعداد اتّصال SSH بين جهازك ومستودع GitHub/GitLab لجعل تعاونك أكثر سلاسة.
تجاهل الملفّات
في بعض الحالات، يجب الإبقاء على ملفّات معيّنة محلّيًا، في هذه الحالة يجب إضافة relative path لهذه الملفّات إلى ملفّ .gitignore الذي يُنشأ تلقائيًا عند تهيئة git. وُجد Github وGitlab بصورة رئيسية لتخزين الشيفرة، لذا لا معنى لإرسال قواعد البيانات أو أوزان Deep Learning إليهما، وعادةً ما تُضاف مساراتها إلى ملفّ .gitignore.
WEIGHTS_DIR/ #ignoring the folder of DL weights
DATA_DIR/ # ignoring the folder of dataجدول مرجعي

للتذكير، توجد طريقتان للتعامل مع versioning بواسطة git في VS Code: إمّا من خلال Gitlens أو من خلال الـ terminal المُثبَّت لديك. لمزيد من التفاصيل، لا تتردّد في زيارة الوثائق الرسمية لـ git.
فلسفة مشروع Git
عند العمل على مشروع، تطبيق على سبيل المثال، من المفيد التفكير في ثلاثة مستويات من الترميز/التفريع:
Master branch: أو الفرع الرئيسي يستضيف نسخة الشيفرة التي يستخدمها مستخدمو التطبيق اليوميون (للإصدارات فقط)Dev branch: يُستخدم لاستضافة التطويرات والميزات الجديدة المُخطّط لها للتطبيقFeature branch: يُنشأ في كلّ مرّة تُطوَّر فيها ميزة جديدة
ملاحظة: إذا استقرّ فرع dev، يمكنك عكسه على فرع آخر يمكن أن يستخدمه مُختبِرو التطبيق، في UAT phase مثلًا، لتجربة الميزات الجديدة والإبلاغ عن الأخطاء في نهاية المطاف.
إرشادات رئيسية
بالنظر إلى workflow الموصوف أعلاه، إليك بعض الأمور المهمّة التي يجب وضعها في الاعتبار:
Master branch:
- لا تُجرِ commit أبدًا في master المحلّي!
- أبقِ فرع master محميًّا!
Dev branch:
- لا تُجرِ commit أبدًا في dev المحلّي!
- أبقِ فرع dev محميًّا!
Feature branch:
- ادفع دائمًا عملك إلى فرعك البعيد حتى لو لم ينتهِ!
- عند التعاون على الفرع نفسه، تجنّب العمل على الملفّ أو الدالّة نفسها!
- تحقّق من الحالة في كلّ مرّة قبل staging:
git status - تحقّق دائمًا من امتلاكك أحدث نسخة من شيفرة dev
العمل على ميزة جديدة
أي إنشاء فرع جديد من فرع dev:
- تحقّق إن كنت في فرع dev:
git branch- إن كان كذلك:
git --rebase origin/dev #Check if you are up-to-date
git checkout -b branchName- إن لم يكن كذلك:
git checkout dev
git --rebase origin/dev
git checkout -b branchName2. أجرِ تغييراتك، وأضفها وأجرِ commit لها
3. ادفع عملك إلى فرعك البعيد:
git push --set-upstream origin branchName4. تأكّد أنّ فرعك محدّث بالنسبة إلى dev:
git checkout branchName
git pull --rebase origin/devحُلّ التعارضات إن وُجدت:
git add path_to_resolved_file
git commit -m "message"
git push #sends automatically to your remote branch5. أنشئ Pull Request في GitHub/Gitlab وعيّن مراجعًا
ملاحظة: Rebase هي تقنية دمج أخرى تُبقي سجلّاتك أنظف
يمكننا تلخيص git flow الموصوف أعلاه في الشكل التالي:

عند إجراء الدمج، ستحتاج إلى التأكّد من أنّ التطبيق يعمل بشكل مثالي وأنّه لا توجد أيّ ارتدادات مقارنةً بالنسخة السابقة، عن طريق تشغيل اختبارات تلقائية. ولهذا السبب تحتاج إلى CI/CD!
CI-CD مع GitLab
تشير CI/CD إلى Continuous Integration وContinuous Delivery/Deployment. إنها مقاربة تقنية تسمح بأتمتة عملية تطوير التطبيقات من خلال تشغيل اختبارات للتحقّق ممّا إذا
- كانت الميزات الجديدة تعمل كما هو متوقَّع
- لم تكن هناك ارتدادات على القديمة منها
تُوفّر Gitlab هذا الخيار، المرتبط بكلّ مشروع، ويقدّم runners أو عمليات تلتقط وتنفّذ jobs الخاصة بـ CI/CD.
يُطوَّر pipeline الخاصّ بـ CI/CD باتّباع 3 خطوات رئيسية:
- تثبيت وتسجيل GitLab Runners
- إنشاء، محلّيًا، ملفّ yml يفصّل jobs/tests المراد إجراؤها
- دفع jobs إلى Gitlab
1. GitLab Runners
كما ذُكر سابقًا، runners هي عمليات تُستخدم لتنفيذ الاختبارات المحدّدة مسبقًا. توجد 3 أنواع:
- Shared runners متاحة لجميع المجموعات والمشاريع في نسخة GitLab.
- Group runners متاحة لجميع المشاريع والمجموعات الفرعية ضمن مجموعة.
- Specific runners مرتبطة بمشاريع محدّدة.
في هذا التمرين، سنتعمّق في specific runners التي تُستخدم لمشروع واحد في كلّ مرّة. لإعداد specific runner يدويًا، نحتاج أوّلًا إلى تثبيت GitLab Runner. للقيام بذلك، على MacOS مثلًا، يمكننا استخدام brew:
brew install gitlab-runner #Install GitLab Runner
brew services start gitlab-runner # Install GitLab Runner as a service and start it.بمجرّد تثبيت runner، سنحتاج إلى تسجيله للمشروع بتشغيل الأمر التالي:
gitlab-runner registerثمّ نحتاج إلى إدخال المعلومات التالية:
- عنوان URL لنسخة GitLab: غالبًا https://gitlab.com/
- رمز التسجيل: يوجد في Repository > Settings > Runners
- وصف لـ runner: وصف قصير لـ runner
- Tags مرتبطة بـ runner
- Executor: العديد من الخيارات للنظر فيها (Docker، ssh، shell…)
2. ملفّ YML
لاستخدام خدمات CI/CD الخاصة بـ GitLab، ستحتاج إلى استضافة مشروعك على المنصّة ووجود ملفّ YAML في جذره يُسمّى .gitlab-ci.yml يستضيف إعدادات CD/CD.
تُجمَّع السكربتات في jobs، وتعمل jobs كجزء من pipeline أكبر. يمكنك تجميع عدّة jobs مستقلّة في stages تعمل بترتيب محدّد. وتُستخدم tags لاختيار runner.
variables:
GIT_DEPTH: 1 #Shallows cloning: Last commit for each file of the project
stages:
- build
- test
#- deploy
install-dependencies: #Job 1
stage: build
tags:
- python
script:
- echo "Install dependencies"
- conda install environment.yml
linting: #Job 2
stage: test
tags:
- python
script:
- echo "check linting"
- pylint
unit-tests: #Job 3
stage: test
tags:
- python
script:
- echo "unit tests"
integration-test: #Job 4
stage: test
tags:
- python
script:
- echo "Integration tests"قبل دفع ملفّك إلى GitLab يمكنك أوّلًا التحقّق من بنيته وتأكيد إعداداته على CI Lint.
3. Pipeline على GitLab
كما هو موضّح في ملفّ yml، تتمثّل إعدادات CI/CD في تشغيل jobs مختلفة تنتمي إلى stages مختلفة مذكورة بترتيب زمني: build وtest وdeploy. تعمل jobs في المرحلة نفسها بالتوازي بينما تعمل jobs في المرحلة التالية بعد اكتمال jobs المرحلة السابقة بنجاح. في كلّ دفع إلى GitLab تُنفَّذ jobs ويتمّ تمرير merge request بمجرّد حساب جميع jobs بنجاح. يمكنك متابعة التنفيذ بفحص CI/CD Pipelines:

ملاحظة: يمكنك استخدام ملفّات yml separate لفرعَي master وdev إذا لم تكن الاختبارات متشابهة.
الخاتمة
Git أداة قويّة جدًّا تُستخدم عالميًا في كلّ تطبيق تقريبًا، خصوصًا تلك التي تضمّ فِرَق تطوير متعدّدة، ومن ثَمَّ الحاجة إلى إتقان هذه التقنية للحصول على pipeline تطوير مستدام وقوي يسمح بتعاون أسرع وأفضل.
