سجل التطوير (Git History) Development History
تتبع رحلة بناء MRE CashBook من البداية، وكيف تطورت الشيفرة البرمجية عبر الزمن. Tracking the journey of building MRE CashBook from the start, and how the code evolved over time.
قبل أي كود، كان لازم نبدأ بـ Version Control عشان نحفظ كل خطوة. بنستخدم Git كأداة أساسية.
Before any code, we had to start with Version Control to save every step. We use Git as our primary tool.
git init
بيحول الفولدر الحالي لمستودع (Repository) محلي، وبيعمل فولدر مخفي اسمه `.git` فيه كل التاريخ.
Converts the current folder into a local repository, creating a hidden `.git` folder containing all history.
git config --global user.name "Your Name"
بيعرف Git مين اللي عمل الـ commit ده. ده مهم جداً في المشاريع الجماعية.
Tells Git who made this commit. This is crucial for collaborative projects.
المشروع مر بمراحل كتير، كل مرحلة كانت بتمثل تحدي تقني مختلف.
The project went through many phases, each representing a different technical challenge.
في أول commits، ركزنا على بناء هيكل يقدر يستوعب ميزات كتير من غير ما الكود يبوظ.
In the first commits, we focused on building a structure that can handle many features without code rot.
lib/
├── core/ # Shared utilities, themes, and config
├── features/ # Business modules (Data, Domain, Presentation)
└── init_di.dart # Dependency Injection setup
فلسفة البداية: "ابني صح من الأول عشان ترتاح في الآخر". استخدام Clean Architecture في البداية وفر علينا ساعات من الـ refactoring لاحقاً.
Founder's Philosophy: "Build it right first to rest later." Using Clean Architecture from the start saved us hours of refactoring later.
في الـ commit رقم 896e52fe، تم إضافة نظام الـ Responses المتقدم اللي بيتعامل مع الـ Tablets والـ iPads.
In commit 896e52fe, we added the advanced Responsive system for Tablets and iPads.
git show 896e52fe
بيعرض التغييرات اللي حصلت في commit معين بالتفصيل (Diff).
Shows changes made in a specific commit in detail (Diff).
| Feature | Reasoning |
|---|---|
| Adaptive Layouts | Switching between BottomNav and NavigationRail. |
| Micro-Spacing | Adjusting padding based on screen width using AppSizes. |
| Constraint Boxes | Preventing forms from taking too much width on Desktops. |
أحد أصعب التحديات كان طباعة اللغة العربية بوضوح في الـ PDF. جربنا حلول كتير لحد ما وصلنا لاستخدام خطوط مخصصة (Custom Fonts) مدمجة.
One of the hardest challenges was printing Arabic clearly in PDFs. we tried many solutions until we settled on embedded custom fonts.
التحدي: مكتبة PDF العادية مش بتدعم الـ RTL (Right-to-Left) بشكل طبيعي، فكان لازم نستخدم مكاتب مساعدة وشغل يدوي لإعادة ترتيب الحروف.
Challenge: Standard PDF libraries don't support RTL naturally, so we used helper libs and manual work to reorder characters.
في الـ commit ccc49420، أضفنا device_preview_screenshot عشان نقدر نولد صور دعائية للتطبيق بسهولة من جوه التطبيق نفسه.
In commit ccc49420, we added device_preview_screenshot to generate promotional images easily from within the app.
كان قرار جريء جداً تغيير اسم المشروع في نص الطريق. ده استلزم تعديلات في أكتر من 50 ملف!
It was a bold decision to change the project name mid-way. It required modifications in over 50 files!
# Original
name: ledger
description: A new Flutter project.
# New
name: mre_cashbook
description: The ultimate financial manager.
كل الـ imports في المشروع كان لازم تتغير من package:ledger/... إلى package:mre_cashbook/.... دي عملية مرهقة لو اتعملت مانيوال.
All imports had to change from package:ledger/... to package:mre_cashbook/.... This is exhausting if done manually.
grep -rl "package:ledger" . | xargs sed -i '' 's/package:ledger/package:mre_cashbook/g'
بتبحث داخل كل الملفات (Recursive) عن جملة "package:ledger" وبتطلع لستة بأسماء الملفات اللي فيها الجملة دي.
Searches within all files (Recursive) for the string "package:ledger" and outputs a list of filenames containing it.
بتاخد لستة الملفات وتنفذ عليهم أمر sed اللي بيعمل استبدال (Replace) للنص القديم بالنص الجديد جوه الفايلات فوراً.
Takes the file list and executes sed, which replaces the old text with the new text inside the files immediately.
تغيير الـ PRODUCT_BUNDLE_IDENTIFIER في iOS والـ applicationId في Android.
Changing PRODUCT_BUNDLE_IDENTIFIER in iOS and applicationId in Android.
تحذير: الخطوة دي بتمسح بيانات الـ Firebase وبتخليك تضطر تعمل App جديد على Firebase Console ببيانات الـ ID الجديد عشان الـ Notifications والـ Analytics يشتغلوا.
Warning: This step disconnects Firebase and forces you to create a new App on Firebase Console with the new ID for Notifications and Analytics to work.
في أول commit للمشروع، تم إنشاء 123 ملفاً دفعة واحدة! دي كانت "البيج بانج" اللي حطت أساسات كل حاجة بنشوفها النهاردة.
In the project's first commit, 123 files were created at once! This was the "Big Bang" that laid the foundations of everything we see today.
123 files changed, 4915 insertions(+)
create mode 100644 lib/main.dart
create mode 100644 pubspec.yaml
create mode 100644 .gitignore
create mode 100644 android/app/src/main/AndroidManifest.xml
create mode 100644 ios/Runner/Info.plist
... and 118 more files
| File | Purpose at Genesis | Details |
|---|---|---|
lib/main.dart |
Entry Point | البداية كانت بسيطة جداً مع Counter app، وبعدها اتحولت لمنصة إدارة مالية. |
pubspec.yaml |
Registry | مكان تعريف المكاتب. أول مجموعة مكاتب كانت للـ UI والـ Fonts بس. |
.gitignore |
Safety | منع رفع ملفات الـ build والـ secrets لـ GitHub. |
android/ folders |
Native Config | تحميل الـ SDKs المطلوبة وتجهيز الـ permissions المبدئية. |
عشان نحافظ على استقرار التطبيق، بنستخدم استراتيجية تشبه الـ GitFlow ولكن بشكل مبسط.
To maintain app stability, we use a simplified GitFlow-like strategy.
- Main Branch: الفرع المقدس، دايماً عليه النسخة المستقرة والقابلة للنشر.
- Dev Branch: فرع التطوير، بنجمع فيه كل الميزات قبل ما نرفعها للـ Main.
- Feature Branches: أي ميزة جديدة بتتعمل في فرع لوحدها (مثل
feat/charts). - Hotfix Branches: لتصليح أي Bug طارئ في النسخة المنشورة.
git checkout -b feat/advanced-filters
بتعمل نسخة جديدة من الكود في "غرفة جانبية" عشان تجرب فيها الفلاتر الجديدة من غير ما تأثر على الكود اللي شغال.
Creates a new code version in a "side room" to experiment with new filters without affecting the working code.
هنا هنمشي خطوة بخطوة مع أهم الأوامر اللي استخدمناها في دورة حياة التطبيق.
Here we'll go step-by-step with the most important commands used in the app's lifecycle.
git log --oneline --graph --all
بيعرض تاريخ المشروع بشكل "شجري" (Tree) ملون، وكل commit في سطر واحد بس.
Displays project history in a colorful "tree" format, with each commit on a single line.
git blame lib/main.dart
بيعرض كل سطر في الفايل ومين المبرمج اللي كتبه وأمتى. مفيد جداً لمعرفة "ليه السطر ده اتكتب كده".
Shows every line in the file, who wrote it, and when. Very useful to know "why this line was written this way".
git stash
بيخبي التعديلات الحالية "على جنب" عشان تقدر تغير الـ branch من غير ما تعمل commit.
Temporarily slides your current changes aside so you can switch branches without committing.
git stash pop
بيرجع التعديلات اللي كنت مخبيها بالـ stash وبيطبقها على الكود الحالي.
Restores the changes you stashed and applies them to the current code.
git reset --soft HEAD~1
بترجع في كلامك عن آخر commit عملته بس بتحافظ على كل مجهودك وتعديلاتك في الـ staging area.
Undoes your last commit but keeps all your work and modifications in the staging area.
عشان تفهم الـ logic بتاع Git صح، لازم تعرف المصطلحات دي كويس:
To understand Git logic, you must know these terms well:
| Term | Meaning (English) | المعنى (عربي) |
|---|---|---|
| Repository (Repo) | Storage space for project history. | المستودع أو "المخزن" اللي فيه تاريخ الكود. |
| Commit | A snapshot of changes at a point in time. | "لقطة" أو سيف للكود في لحظة معينة. |
| Stage (Index) | Preparation area before committing. | منطقة "التحضير" قبل ما تعمل السيف النهائي. |
| Branch | A parallel version of the codebase. | فرع أو نسخة موازية من الكود للتجربة. |
| Merge | Combining changes from different branches. | دمج التعديلات من فرع للتاني. |
| Conflict | When two changes overlap at same line. | تضارب (لما مبرمجين يغيروا نفس السطر). |
| Remote | Copy of project hosted on servers (GitHub). | النسخة المرفوعة أونلاين (زي GitHub). |
| Fetch | Download updates without merging. | تحميل التحديثات من غير ما تدمجها في كودك. |
| Pull | Fetch + Merge in one command. | تحميل التحديثات ودمجها فوراً. |
| Push | Upload your local commits to Remote. | رفع تعديلاتك من جهازك للسيرفر. |
| Cherry-pick | Applying a specific commit from one branch to another. | اختيار commit معين بس ونقله لفرع تاني. |
| Rebase | Moving or combining a sequence of commits to a new base commit. | إعادة ترتيب الـ commits عشان يبانوا كأنهم اتعملوا ورا بعض. |
عشان نحافظ على سجل نضيف، بنتبع القواعد دي:
To maintain a clean history, we follow these rules:
بنبدأ كل رسالة بنوع التعديل:
feat:لإضافة ميزة جديدة.fix:لتصليح bug.refactor:لتحسين الكود من غير تغيير وظيفته.chore:لتعديلات بسيطة (زي تحديث مكتبة).
كل commit لازم يعمل "حاجة واحدة بس". مبيكونش فيه تصليح bug مع ميزة جديدة في نفس الوقت.
Every commit must do "exactly one thing". No mixing bug fixes with new features.
التضارب بيحصل لما مبرمجين يغيروا نفس السطر في نفس الملف ويرفعوا كودهم في نفس الوقت. Git بيفقد القدرة على الدمج التلقائي وبيطلب تدخل بشري.
Conflicts happen when two devs change the same line in the same file and push at the same time. Git loses auto-merge ability and asks for human intervention.
<<<<<<< HEAD
static const String appName = 'MRE CashBook';
=======
static const String appName = 'CashBook Pro';
>>>>>>> feature/branding-update
<<<<<<< HEAD: الكود اللي عندك حالياً.=======: الخط الفاصل.>>>>>>> feature-branch: الكود اللي جاي من الفرع التاني.
لازم تختار كود واحد، أو تدمجهم مع بعض، وتمسح الرموز دي (Markers) وبعدين تعمل git add.
You must pick one version, or merge them, delete the markers, then run git add.
git merge --abort
بترجع الكود لحالته قبل ما تبدأ عملية الدمج الفاشلة. مفيدة لو الدنيا باظت منك وعاوز ترجع لنقطة الصفر.
Reverts everything back to the state before the failed merge. Useful if things got messy and you want to start over.
في MRE CashBook، بنستخدم الـ Hooks عشان نمنع رفع كود فيه أخطاء (Linting errors).
In MRE CashBook, we use Hooks to prevent pushing code with Linting errors.
ده سكريبت بيتفذ أوتوماتيك أول ما تدوس git commit. لو الـ Analyze بتاع Flutter لقى غلطة، الـ commit بيفشل.
A script that auto-runs when you hit git commit. If Flutter Analyze finds an error, the commit fails.
flutter analyze && flutter test
أول جزء بيفحص جودة الكود (Static Analysis)، وتاني جزء (بعد &&) بيشغل الاختبارات. الـ && معناها "لو الأول نجح، شغل التاني".
First part checks code quality, second part (after &&) runs tests. && means "if first succeeds, run second".
دايماً حط ملفات .g.dart و .freezed.dart في الـ .gitignore لو كنت بتستخدم Code Generation، عشان متملقاش الـ commits بتغييرات أوتوماتيكية.
Always ignore .g.dart and .freezed.dart in .gitignore if using Code Gen, to avoid cluttering commits.
وفر وقتك واعمل اختصارات للأوامر الطويلة.
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
لو عملت commit كل ما تخلص ويدجت واحدة، هتقدر ترجع في كلامك بسهولة لو حاجة باظت، بدل ما تضطر تمسح شغل يوم كامل.
Committing after finishing one widget lets you revert easily if something breaks, instead of losing a whole day's work.
خلاصة الخبرة: الكود هو السكن، والـ Git هو التأمين. لا تبخل على تأمين مستقبلك التقني.
Expert's Take: Code is the house, Git is the insurance. Don't skimp on securing your technical future.
لأننا مغيرناش بس الاسم اللي بيظهر لليوزر، إحنا غيرنا الـ Package Name والـ Folder Structure والـ Configuration بتاع Firebase. كل ده كان لازم يتم بدقة عشان التطبيق ميفقدش القدرة على الاتصال بالسيرفر.
Because we didn't just change the display name; we changed the Package Name, Folder Structure, and Firebase config. Everything had to be done precisely so the app wouldn't lose server connectivity.
كان فيه commit بدري جداً حاولنا فيه نستخدم قاعدة بيانات NoSQL، بس اكتشفنا إن الـ Data Relations في MRE معقدة جداً ومحتاجة SQL وقوة Drift. عملنا git revert ورجعنا للـ Drift.
There was a very early commit where we tried using NoSQL, but we discovered that MRE data relations are complex and needed SQL and Drift's power. We performed a git revert and went back to Drift.
بفضل الـ History، قدرنا نقارن بين أكتر من 5 نسخ لمكتبات PDF مختلفة ونشوف مين اللي كان بيسبب تهنيج في الجهاز (Memory Leak) ومين اللي كان بيدعم العربي صح.
Thanks to History, we could compare over 5 versions of different PDF libraries to see which one caused memory leaks and which one supported Arabic correctly.
نعم، واستخدام Git Branches مهم جداً هنا عشان نرفع الـ Pathches لـ Shorebird من غير ما نغير نسخة الـ Store الأساسية.
Yes, and using Git branches is crucial here to push patches to Shorebird without changing the main store version.
اتعلمنا في الفصل ده إن الكود مش بس ملفات، ده تاريخ من القرارات. فهمنا إزاي Git بيحمينا وإزاي نتتبع التغييرات الكبيرة زي الـ Rebranding والـ Adaptive UI.
In this chapter, we learned that code isn't just files—it's a history of decisions. We understood how Git protects us and how to track major changes like Rebranding and Adaptive UI.
تذكر: الـ Git History هو "ذاكرة" المشروع. المبرمج الشاطر هو اللي بيسيب رسائل واضحة وتاريخ نضيف للي هيجي بعده.
Remember: Git History is the "memory" of the project. A good dev leaves clear messages and clean history for those who follow.
- المحطة الجاية: هندخل جوه الفولدرات ونشوف توزيعة الملفات في الفصل الثالث: هيكل المشروع.
Next Stop: We'll go inside the folders and see the file distribution in Chapter 03: Project Structure.