
... قمنا بتطوير Gardenscapes. لا يزال لديها آثار من Gardenscapes القديمة تحت Windows. لم تكن حتى مطابقة 3 ، بل كائن مخفي. ولا أحد يستطيع حتى تخيل الارتفاعات التي ستصل إليها اللعبة.
ثم يوم جيد ...
كيف بدأ كل شيء
عند الوصول إلى المستودع ، رأينا الرسالة التالية:
"تم تعطيل هذا المستودع. تم تعطيل الوصول إلى هذا المستودع من قبل موظفي GitHub بسبب الاستخدام المفرط للموارد ، في انتهاك لشروط الخدمة الخاصة بنا. الرجاء الاتصال بالدعم لاستعادة الوصول إلى هذا المستودع. اقرأ هنا لمعرفة المزيد حول تقليل حجم المستودع الخاص بك. "
كما قد تكون خمنت ، نستخدم github لاستضافة مستودعات git. وهكذا ، فجأة ودون إعلان الحرب ، قام جيثب بسد مستودعنا لتجاوزه الحد الأقصى للحجم المسموح به. الرقم الدقيق لم يذكر على موقعهم على الانترنت. في وقت القفل ، كان حجم المجلد .git حوالي 25 جيجابايت. (ملاحظة 2020: أصبحت الحدود الآن أعلى ، وينص موقع github صراحةً على أن حجم المستودع يجب ألا يتجاوز 100 جيجابايت).
كيف تمكنا من إنشاء مثل هذا المستودع الكبير؟ السبب واضح: نقوم بتخزين الملفات الثنائية فيه. مكتوب في كل مكان أنه لا ينصح بعمل هذا ، لكنه أسهل بكثير بالنسبة لنا. نريد إطلاق اللعبة من المستودع فورًا دون بذل جهد إضافي. لذلك ، نلتزم بالرسومات وموارد الألعاب الأخرى في المستودع.
لكن هذا ليس سيئا للغاية. درس مهم تعلمناه من هذه القصة بأكملها: لا
الكفاح من أجل التاريخ
لذلك ، لا شيء يعمل مع أي شخص. أخبرنا الفريق أنه سيتعين عليهم العمل محليًا لمدة يوم واحد ، لكن لا يبذلوا جهدًا كبيرًا ، وإلا فسيتم حل النزاعات لاحقًا (كان الجميع مستائين جدًا وغادروا على الفور لتناول الشاي) وبدأوا يفكرون فيما يجب عليهم فعله. من الواضح أن هناك حاجة إلى مستودع جديد ، ولكن ما الذي يجب الالتزام به هناك؟ طريقة سهلة هي الوضع الحالي لجميع الفروع. لكننا لم نحب ذلك كثيرًا ، لأن تاريخ التغييرات سوف يضيع ، وسوف ينكسر أمر git blame المفضل لدى الجميع ، وسيتحول كل شيء إلى شقلبة. لذلك ، قررنا القيام بذلك: محو محفوظات الملفات الثنائية ، والاحتفاظ بمحفوظات الملفات النصية.

الخطوة 1. حذف محفوظات الثنائيات
كان لدينا نسخة محلية كاملة من المستودع. أول شيء وجدناه هو الأداة المساعدة الممتازة BFG Repo-Cleaner . إنه بسيط جدًا وسريع جدًا في نفس الوقت ، والاسم جيد.
مثال على سيناريو التنفيذ:
java -jar bfg.jar bfg --delete-files *.{pvrtc,webp,png,jpeg,fla,swl,swf,pbi,bin,mask,ods,ogv,ogg,ttf,mp4} path_to_repository
تحتوي المعلمات على جميع امتدادات الملفات الثنائية التي يمكننا التوصل إليها. من جميع الالتزامات في العالم ، سيتم حذف المعلومات حول الملفات ذات هذه الامتدادات. الأداة المساعدة ذكية وعند حذف محفوظات الملف ، فإنها تترك أحدث إصدار لها. بالإضافة إلى ذلك ، سيتم تضمين هذا الإصدار الأخير في أحدث التزام في الفرع. أردنا أيضًا حذف محفوظات ملفات exe و dll ، لكن الأداة أعطت خطأ. على ما يبدو ، لسبب ما ، يحظر المعالجة في شكل * .exe. علاوة على ذلك ، إذا حددت ملفًا بشكل صريح ، على سبيل المثال ، Gardenscapes.exe ، فسيعمل كل شيء. (ملاحظة 2020: ربما تم إصلاح الخطأ بالفعل).
الخطوة 2. ضغط المستودع
بعد الخطوة الأولى ، لا يزال حجم المستودع كبيرًا. والسبب في ذلك هو طريقة عمل git. أزلنا روابط الملفات فقط ، لكن الملفات نفسها بقيت.
لحذف الملفات فعليًا ، تحتاج إلى تشغيل الأمر git gc ، وهو:
git reflog expire --expire=now --all
و بعد:
git gc --prune=now --aggressive
هذا هو تسلسل الأوامر الموصى به من قبل مؤلف الأداة المساعدة. هنا gc يستغرق وقتًا طويلاً حقًا. بالإضافة إلى ذلك ، مع إعدادات المستودع الافتراضية ، لا يمتلك عميل git ذاكرة كافية لإكمال العملية ويحتاج إلى بعض الرقص مع الدف. (ملاحظة 2020: في ذلك الوقت كان لدينا إصدار 32 بت من git. على الأرجح ، لم تعد هذه المشكلات موجودة في الإصدار 64 بت).
الخطوة الثالثة. الكتابة تلتزم بالمستودع الجديد
اتضح أن هذا هو الجزء الأكثر إثارة للاهتمام في المهمة.
لفهم ما يلي ، تحتاج إلى فهم كيفية عمل git. يمكنك قراءة المزيد حول git في العديد من الأماكن ، بما في ذلك مدونتنا:
- Git: نصائح للمبتدئين - الجزء الأول
- Git: نصائح للمبتدئين - الجزء الثاني
- Git: نصائح للمبتدئين - الجزء الثالث
لذلك ، لدينا عدد كبير جدًا جدًا من الالتزامات محليًا ، هذه الالتزامات صحيحة ، أي بدون تاريخ الثنائيات. يبدو أنه يكفي تنفيذ git push وسيعمل كل شيء بنفسه. لكن لا!
إذا قمت بتنفيذ الأمر git push -u master، ثم يبدأ git بمرح عملية تحميل البيانات إلى الخادم ، لكنه يتعطل بسبب خطأ يبلغ حوالي 2 جيجا بايت. هذا يعني أنك لن تكون قادرًا على تحميل الكثير من الالتزامات دفعة واحدة. سنأكل الفيل في أجزاء. لقد توصلنا إلى أن 2000 التزام قد يصلح حجم 2 جيجابايت. كان الحجم الإجمالي لمستودعنا في ذلك الوقت حوالي 20000 التزام ، موزعة على 4 فروع: master-v101-v102-v103. (ملاحظة 2020: أيها الشباب! منذ ذلك الحين ، أصبح كل شيء أكثر جدية. يوجد بالفعل أكثر من 100000 التزام في هذا المستودع ، وهناك العشرات من فروع الإصدار. وفي الوقت نفسه ، ما زلنا نندرج في حدود Github)
أولاً وقبل كل شيء ، نحن نأخذ في الاعتبار عدد الالتزامات في الفروع عندما أمر المساعدة:
git rev-list --count <branch-name>
على سبيل المثال ، هناك ما يقرب من 10000 التزام في الفرع الرئيسي. الآن يمكننا استخدام الصيغة الموسعة لأمر git push ، وهي:
git push -u origin HEAD~8000:refs/origin/master
HEAD ~ 8000: refs / origin / master هي ما يسمى refspec. يقول الجانب الأيسر أنك بحاجة إلى الالتزام بالتعهد الذي يبعد 8000 عن HEAD ، أي حوالي 2000 التزام. والجانب الأيمن هو أنك تحتاج إلى دفعهم إلى الفرع الرئيسي البعيد. المسار الكامل إلى الفرع المراجع / الأصل / الرئيسي مطلوب هنا.
بعد ذلك ، لا يوجد حتى الآن فرع رئيسي ، وعلى سبيل المثال ، لن يتمكن git fetch من تنزيله. هذا ليس مفاجئًا - بعد كل شيء ، الالتزام الذي يشير إلى رأسها غير موجود بعد. ومع ذلك ، بتكرار الأمر git push HEAD ~ 8000: refs / origin / master ، رأينا الإجابة بأن هذه الالتزامات موجودة بالفعل على الخادم ، وبالتالي ، يتم العمل بعد كل شيء.
بعد ذلك ، اعتقدنا أن العملية واضحة ويمكن إسناد باقي العمل إلى البرنامج النصي. سيكون الالتزام الأخير كبيرًا جدًا ، حيث سيتم تضمين جميع الثنائيات فيه. لذلك ، فقط في حالة ، يتم ملء آخر 10 التزامات بشكل منفصل. تحول النص على النحو التالي:
git push origin HEAD~6000:refs/origin/master
git push origin HEAD~5000:refs/origin/master
git push origin HEAD~4000:refs/origin/master
git push origin HEAD~3000:refs/origin/master
git push origin HEAD~2000:refs/origin/master
git push origin HEAD~1000:refs/origin/master
git push origin HEAD~10:refs/origin/master
git push origin master
git checkout v101
git push -u origin HEAD~1000:refs/origin/v101
git push origin HEAD~10:refs/origin/v101
git push origin v101
git checkout v102
… ..
وهذا يعني أننا نكتب باستمرار جميع فروعنا إلى الخادم ، 2000 التزام لكل دفعة ، وآخر 10 عمليات التزام على حدة.
استغرقت هذه القصة بأكملها وقتًا طويلاً ، وتم عرض الساعة بالقرب من 12 ليلاً. لذلك تركنا النص ليعمل بين عشية وضحاها ، قلنا الصلوات المناسبة لكثولو (ملاحظة 2020: كان لا يزال شائعًا نسبيًا في ذلك الوقت) وعدنا إلى المنزل.
الاخير. نهاية سعيدة
في الصباح ، بعد أن فتحنا المستودع على موقع github ، تأكدنا من أن النص يعمل بنجاح وأن جميع الالتزامات والفروع في مكانها الصحيح.
نتيجة لذلك: تم تقليل حجم المستودع (مجلد .git) من 25 جيجابايت إلى 7.5 جيجابايت. في الوقت نفسه ، يتم الاحتفاظ بكل سجل الالتزام المهم - كل شيء باستثناء الثنائيات. شرب مصممو اللعبة الشاي أكثر من المعتاد. حصل المبرمجون على تجربة لا تُنسى. وبدأوا على وجه السرعة في التفكير في كيفية القيام بذلك حتى لا يكون من الضروري إلزام الملف القابل للتنفيذ في المستودع ، ولكن سيكون من المناسب العمل معه.