Git Pull Force - كيفية الكتابة فوق التغييرات المحلية باستخدام Git

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

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

سير العمل النموذجي

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

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

عند الانتهاء من مهمة ، حان الوقت للمزامنة مع المستودع البعيد. تريد سحب التغييرات عن بُعد لمواكبة تقدم المشروع ، وتريد دفع التغييرات المحلية لمشاركة عملك مع الآخرين.

التغييرات المحلية

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

ومع ذلك ، هناك أوقات تقوم فيها أنت وزملاؤك بإدخال تغييرات في نفس المكان في نفس الوقت. وهذا هو المكان الذي تبدأ فيه المشاكل عادةً.

هل سبق لك أن نفذت git pullفقط لرؤية اللعين error: Your local changes to the following files would be overwritten by merge:؟ عاجلاً أم آجلاً ، يواجه الجميع هذه المشكلة.

الأمر الأكثر إرباكًا هنا هو أنك لا تريد دمج أي شيء ، فقط اسحب ، أليس كذلك؟ في الواقع ، السحب أكثر تعقيدًا قليلاً مما كنت تعتقد.

ما مدى دقة عمل Git Pull؟

السحب ليس عملية واحدة. يتكون من جلب البيانات من الخادم البعيد ثم دمج التغييرات مع المستودع المحلي. يمكن إجراء هاتين العمليتين يدويًا إذا كنت تريد:

git fetch git merge origin/$CURRENT_BRANCH

و origin/$CURRENT_BRANCHسيلة جزء ما يلي:

  • سيقوم Git بدمج التغييرات من المستودع البعيد المسمى origin(الذي نسخت منه)
  • التي تمت إضافتها إلى $CURRENT_BRANCH
  • التي لم تكن موجودة بالفعل في فرعك المحلي المعار

نظرًا لأن Git لا يقوم بعمليات الدمج إلا في حالة عدم وجود تغييرات غير ملتزمة بها ، فكل مرة تقوم فيها بإجراء git pullتغييرات غير ملتزمة بها قد يوقعك في مشكلة. لحسن الحظ ، هناك طرق للخروج من المشاكل بقطعة واحدة!

نحن عائلة

مقاربات مختلفة

عندما يكون لديك تغييرات محلية غير ملتزمة ولا تزال ترغب في سحب إصدار جديد من الخادم البعيد ، فإن حالة الاستخدام الخاصة بك تقع عادةً في أحد السيناريوهات التالية. إما:

  • لا تهتم بالتغييرات المحلية وتريد استبدالها ،
  • تهتم كثيرًا بالتغييرات وترغب في تطبيقها بعد التغييرات عن بُعد ،
  • كنت تريد تنزيل التعديلات عن بعد ولكن لم تقم بتطبيقها بعد

كل نهج يتطلب حلا مختلفا.

أنت لا تهتم بالتغييرات المحلية

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

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

git fetch git reset --hard HEAD git merge origin/$CURRENT_BRANCH

إذا كنت لا تريد أن اكتب اسم فرع في كل مرة تقوم بتشغيل هذا الأمر، بوابة لديه اختصار لطيفة لافتا إلى فرع المنبع: @{u}. الفرع الرئيسي هو الفرع الموجود في المستودع البعيد الذي تدفع إليه وتجلب منه.

هكذا ستبدو الأوامر المذكورة أعلاه مع الاختصار:

git fetch git reset --hard HEAD git merge '@{u}'

نحن نقتبس الاختصار في المثال لمنع الغلاف من تفسيره.

أنت تهتم كثيرًا بالتغييرات المحلية

عندما تكون تغييراتك غير الملتزم بها مهمة بالنسبة لك ، فهناك خياران. يمكنك الالتزام بها ثم الأداء git pull، أو يمكنك إخفاؤها.

يعني التخزين وضع التغييرات بعيدًا للحظة لإعادتها لاحقًا. لكي تكون أكثر دقة ، قم git stashبإنشاء التزام غير مرئي في فرعك الحالي ، ولكن لا يزال بإمكان Git الوصول إليه.

لإعادة التغييرات المحفوظة في المخبأ الأخير ، يمكنك استخدام git stash popالأمر. بعد تطبيق التغييرات المخبأة بنجاح ، يقوم هذا الأمر أيضًا بإزالة التزام التخزين المؤقت لأنه لم يعد هناك حاجة إليه.

يمكن أن يبدو سير العمل كما يلي:

git fetch git stash git merge '@{u}' git stash pop

بشكل افتراضي ، ستصبح التغييرات من المخزن على مراحل. إذا كنت ترغب في فكها ، فاستخدم الأمر git restore --staged(إذا كنت تستخدم Git أحدث من 2.25.0).

أنت فقط تريد تنزيل التغييرات عن بُعد

السيناريو الأخير مختلف قليلاً عن السابق. لنفترض أنك في منتصف عملية إعادة بناء فوضوي للغاية. لا يعد فقدان التغييرات أو إخفائها خيارًا. ومع ذلك ، ما زلت ترغب في إتاحة التغييرات عن بُعد لتشغيلها git diff.

كما اكتشفت على الأرجح ، فإن تنزيل التغييرات عن بُعد لا يتطلب git pullعلى الإطلاق! git fetchيكفي فقط.

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

بعض الأتمتة

هل سمعت عن Git Config؟ إنه ملف يخزن فيه Git جميع الإعدادات التي تم تكوينها بواسطة المستخدم. إنه موجود في الدليل الرئيسي الخاص بك: إما كـ ~/.gitconfigأو ~/.config/git/config. يمكنك تعديله لإضافة بعض الأسماء المستعارة المخصصة التي سيتم فهمها على أنها أوامر Git.

على سبيل المثال ، للحصول على اختصار مكافئ لـ git diff --cached(يظهر الفرق بين الفرع الحالي والملفات المرحلية) ، يمكنك إضافة القسم التالي:

[alias] dc = diff --cached

After that, you can run git dc whenever you wish to review the changes. Going this way, we can set up a few aliases related to the previous use cases.

[alias] pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}" pf = pull_force pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"

This way, running git pull_force will overwrite the local changes, while git pull_stash will preserve them.

The Other Git Pull Force

Curious minds may have already discovered that there is such a thing as git pull --force. However, this is a very different beast to what's presented in this article.

It may sound like something that would help us overwrite local changes. Instead, it lets us fetch the changes from one remote branch to a different local branch. git pull --force only modifies the behavior of the fetching part. It is therefore equivalent to git fetch --force.

Like git push, git fetch allows us to specify which local and remote branch do we want to operate on. git fetch origin/feature-1:my-feature will mean that the changes in the feature-1 branch from the remote repository will end up visible on the local branch my-feature. When such an operation modifies the existing history, it is not permitted by Git without an explicit --force parameter.

Just like git push --force allows overwriting remote branches, git fetch --force (or git pull --force) allows overwriting local branches. It is always used with source and destination branches mentioned as parameters. An alternative approach to overwriting local changes using git --pull force could be git pull --force "@{u}:HEAD".

Conclusion

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

يساعدك تعلم حالات الاستخدام الفعلي على فهم كيفية عمل Git بشكل أفضل. وهذا بدوره سيجعلك تشعر بالقوة كلما وقعت في مشكلة. كلنا نفعل ذلك من وقت لآخر.