git checkout
تبديل الفروع أو استعادة ملفات شجرة العمل
git checkout أمر متعدد الاستخدامات: يبدّل الفروع، وينشئ فروعًا جديدة، ويستعيد ملفات من commits محددة، ويمكنه وضع مستودعك في حالة «HEAD منفصل». ومع أن إصدارات Git الأحدث وزّعت بعض وظائفه على «git switch» و«git restore»، ما زال checkout شائع الاستخدام ومفهومًا على نطاق واسع.
الصيغة
git checkout <branch>
git checkout -b <new-branch> [<start-point>]
git checkout -B <branch> [<start-point>]
git checkout --detach [<branch>]
git checkout [--] <pathspec>...
git checkout <commit> -- <pathspec>...الخيارات
اختيار الخيار المناسب
إنشاء الفروع
طرق مختلفة لإنشاء فرع جديد والانتقال إليه
| الأمر | إن كان الفرع موجودًا | التاريخ | الأنسب لـ |
|---|---|---|---|
-b <name> | يفشل بخطأ | عادي (موصول) | العمل المعتاد على ميزة جديدة |
-B <name> | يُعاد ضبطه على الـ commit الحالي | عادي (موصول) | إعادة بدء فرع من الصفر |
--orphan <name> | يفشل بخطأ | لا شيء (مفصول) | gh-pages، التوثيق، صفحة بيضاء |
التبديل مع تغييرات غير محفوظة
ما يحدث لتعديلاتك المحلية عند تبديل الفروع
| الأمر | تغييرات غير محفوظة | مستوى الخطر | متى تستخدمه |
|---|---|---|---|
git checkout <branch> | ممنوع عند التعارض | آمن | السلوك الافتراضي - يمنع الحوادث |
git checkout -f <branch> | تُحذف نهائيًا | خطير | التخلّي عمدًا عن كل التغييرات المحلية |
git checkout -m <branch> | تُدمج بدمج ثلاثي | متوسط | نقل التغييرات إلى فرع آخر |
git stash + checkout | محفوظة لوقت لاحق | آمن | تبديل سياق مؤقت |
استعادة الملفات
التخلّص من محتوى الملفات أو استعادته من مصادر مختلفة
| الأمر | المصدر | يؤثر في التجهيز | قابل للاستعادة |
|---|---|---|---|
-- <file> | الفهرس (النسخة المجهّزة) | No | لا - التغييرات تضيع إلى الأبد |
<commit> -- <file> | commit محدد | نعم (مجهَّز) | لا - لكنه مجهَّز للمراجعة |
-p -- <file> | الفهرس (تفاعلي) | No | جزئي - اختر الأجزاء |
تتبّع الفروع البعيدة
التحكم في العلاقة بين الفروع المحلية والبعيدة
| الأمر | ينشئ تتبّعًا | حالة الاستخدام | git push/pull |
|---|---|---|---|
--track origin/feat | نعم (تلقائيًا) | العمل على فرع زميل | يعمل دون وسائط |
--no-track -b exp origin/main | لا (مستقل) | التجربة بأمان | يتطلب تحديد المستودع البعيد |
<remote-branch> | نعم (إن لم يكن هناك لبس) | سحب سريع لفرع بعيد | يعمل دون وسائط |
حل تعارضات الدمج
اختيار طرف أثناء تعارضات الدمج
| الأمر | يُبقي | يتخلّص | متى تستخدمه |
|---|---|---|---|
--ours <file> | نسخة فرعك | التغييرات الواردة | تغييراتك هي الصحيحة |
--theirs <file> | النسخة الواردة | تغييراتك | قبول تنفيذهم |
(manual edit) | نتيجة مدمجة | لا شيء | تحتاج أجزاء من الطرفين |
checkout مقابل الأوامر الحديثة
قسّم Git 2.23+ الأمر checkout إلى أوامر مركّزة
| الأمر | يبدّل الفروع | يستعيد الملفات | يُنصح به لـ |
|---|---|---|---|
git checkout | نعم | نعم | الاعتياد، إصدارات Git القديمة |
git switch | نعم | No | نية واضحة: عمليات الفروع فقط |
git restore | No | نعم | نية واضحة: عمليات الملفات فقط |
أمثلة على سير العمل
git stashاحفظ العمل الحالي غير المحفوظ
git checkout other-branchانتقل إلى الفرع الآخر
(review or make quick fix)أنجز العمل المطلوب على هذا الفرع
git checkout -عُد إلى الفرع السابق (اختصار)
git stash popاستعد عملك المحفوظ
git checkout mainانتقل إلى الفرع main
git pull origin mainاحصل على أحدث التغييرات من المستودع البعيد
git checkout -b feature-nameأنشئ فرع الميزة الجديد وانتقل إليه
(make changes and commits)اعمل على الميزة
git push -u origin feature-nameادفع الفرع واضبط التتبّع
git statusاعرف الملفات التي عُدّلت
git diff file.jsراجع التغييرات التي ستتخلّص منها
git checkout -- file.jsتخلّص من تغييرات ملف محدد
git checkout -- .أو تخلّص من كل التغييرات غير المجهّزة في الملفات المتتبَّعة
git log --onelineاعثر على hash الـ commit الذي تحتاجه
git checkout <commit-hash>اسحب ذلك الـ commit المحدد (HEAD منفصل)
(inspect, test, or debug)افحص الشيفرة القديمة
git checkout mainعُد إلى الفرع main عند الانتهاء
git log --oneline -- file.jsاعثر على الـ commits التي غيّرت هذا الملف
git show <commit>:file.jsعاين النسخة القديمة
git checkout <commit> -- file.jsاستعد الملف من ذلك الـ commit (يصبح مجهَّزًا)
git commit -m 'Restore file.js'احفظ النسخة المستعادة في commit
git fetch originاحصل على أحدث معلومات الفروع البعيدة
git branch -rاعرض الفروع البعيدة المتاحة
git checkout --track origin/featureأنشئ فرعًا محليًا يتتبّع البعيد
git pullالآن يعمل pull دون تحديد المستودع البعيد
حل المشكلات
error: Your local changes to the following files would be overwritten by checkout
السبب: لديك تغييرات غير محفوظة تتعارض مع الفرع الهدف
احفظ تغييراتك في commit، أو خبّئها بـ stash، أو استخدم -f للإجبار (يتخلّص من التغييرات)
git stash && git checkout branch && git stash poperror: pathspec 'branch-name' did not match any file(s) known to git
السبب: الفرع غير موجود، أو ربما أخطأت في كتابة الاسم
اعرض الفروع المتاحة بـ git branch -a، أو أنشئ الفرع بـ -b
git branch -a | grep branch-nameYou are in 'detached HEAD' state
السبب: سحبت hash لـ commit أو وسمًا بدل اسم فرع
إن أردت مواصلة العمل فأنشئ فرعًا. وإلا فاسحب فرعًا موجودًا
git checkout -b new-branch-nameضياع الـ commits المنفَّذة في حالة HEAD منفصل
السبب: نفّذت commits في حالة HEAD منفصل ثم انتقلت إلى فرع آخر
اعثر على الـ commits عبر الـ reflog وأنشئ فرعًا لحفظها
git reflog && git branch recovered-work <commit-hash>تعذّر الـ checkout: سيُكتب فوق ملف غير متتبَّع
السبب: لديك ملفات غير متتبَّعة موجودة في الفرع الهدف
احذف الملفات غير المتتبَّعة أو انقلها أو خبّئها أولًا
git stash --include-untracked && git checkout branchتخلّصت من تغييرات بالخطأ بـ checkout --
السبب: يحذف git checkout -- <file> التغييرات غير المحفوظة نهائيًا
للأسف، لا يستطيع Git استعادتها. راجع السجل المحلي في محررك
(check IDE local history if available)fatal: 'name' could be both a local file and a tracking branch
السبب: ملف أو مجلد يحمل اسم الفرع البعيد نفسه الذي تريد سحبه
أضف -- في النهاية لتخبر Git أن الاسم فرع، أو استخدم git switch
git checkout branch-name --الفرع لا يتحدّث بعد الـ checkout
السبب: ربما سحبت فرع تتبّع بعيد مباشرة
أنشئ فرع تتبّع محليًا بدل سحب origin/branch مباشرة
git checkout --track origin/branch-nameنصائح وأخطاء شائعة
أفضل الممارسات
- ✓استخدم 'git stash' قبل تبديل الفرع إن كان لديك عمل غير محفوظ في commit تريد إبقاءه
- ✓فضّل 'git checkout -b' على 'git branch' + 'git checkout' منفصلين لإنشاء فرع والانتقال إليه
- ✓استخدم '--' لفصل مسارات الملفات عن أسماء الفروع بوضوح: 'git checkout -- file.txt'
- ✓فكّر في الأوامر الحديثة 'git switch' للفروع و'git restore' للملفات - النية أوضح
- ✓استخدم 'git checkout -' للعودة سريعًا إلى الفرع السابق (مثل 'cd -')
- ✓قبل استخدام '-f' لإجبار الـ checkout، تأكد أنك تريد فعلًا التخلّص من تغييراتك
- ✓في حالة HEAD منفصل، أنشئ فرعًا فورًا إن كنت تنوي تنفيذ commits
- ✓استخدم '--track' عند سحب الفروع البعيدة لضبط الدفع والسحب تلقائيًا
- ✓استخدم 'git checkout <commit> -- <file>' لاستعادة ملفات محددة دون تبديل الفرع
- ✓تجنّب سحب commits مباشرة إلا للتحقيق - استخدم أسماء الفروع للعمل المعتاد
- ✓استخدم '-p' (وضع patch) عندما تريد التخلّص من بعض التغييرات فقط في ملف
- ✓تحقّق دائمًا أنك على الفرع الصحيح بـ 'git branch' أو 'git status' قبل بدء العمل
أخطاء متكررة
- ✗محاولة الـ checkout مع تغييرات غير محفوظة. يرفض Git التبديل إن كان سيكتب فوق تغييراتك - نفّذ commit أو stash، أو استخدم -f للإجبار (يتخلّص من التغييرات).
- ✗الخلط بين checkout للفروع وcheckout للملفات. استعادة ملفات بالخطأ عند محاولة تبديل الفرع - ضع -- قبل مسارات الملفات: git checkout -- file.txt
- ✗تنفيذ commits في حالة HEAD منفصل. تصبح هذه الـ commits يتيمة عند سحب فرع آخر - أنشئ فرعًا أولًا: git checkout -b my-branch
- ✗استخدام -B دون فهم أنه يكتب فوق الموجود. قد يضيّع موضع الفرع الموجود - استخدم -b للفروع الجديدة، و-B فقط عند إعادة الضبط عن قصد.
الأسئلة الشائعة
'git switch' أمر أحدث (Git 2.23+) لا يفعل إلا تبديل الفروع، مما يجعله أوضح وأكثر أمانًا. أما 'git checkout' فيبدّل الفروع ويستعيد الملفات معًا، وهذا قد يربك. استخدم 'git switch' للفروع و'git restore' للملفات إن كنت تفضّل الطريقة الحديثة.
للأسف، لا يمكن ذلك بـ Git وحده - تُحذف التغييرات نهائيًا. بعض بيئات التطوير فيها سجل محلي قد يساعد. لهذا يجب الحذر مع هذا الأمر.
يعني HEAD منفصل أنك سحبت commit محددًا بدل فرع. يمكنك الاستكشاف وتنفيذ commits، لكنها لن تنتمي إلى أي فرع. أنشئ فرعًا بـ 'git checkout -b name' لحفظ عملك.
'-b' ينشئ فرعًا جديدًا ويفشل إن كان موجودًا أصلًا. '-B' ينشئ فرعًا جديدًا أو يعيد ضبط فرع موجود على الموضع الحالي. استخدم '-B' عندما تريد إعادة ضبط فرع عن قصد.
استخدم 'git checkout other-branch -- path/to/file'. هذا ينسخ الملف من ذلك الفرع إلى مجلد عملك ومنطقة التجهيز. ثم يمكنك حفظه في commit على فرعك الحالي.
يحميك Git من فقدان العمل. إن كان تبديل الفرع سيكتب فوق تغييراتك، فإنه يرفض. احفظ تغييراتك في commit، أو خبّئها بـ 'git stash'، أو استخدم 'git checkout -f' للإجبار (وهذا يتخلّص من التغييرات).
ينقلك إلى الفرع الذي سحبته سابقًا، مثل 'cd -' في الـ shell. طريقة سريعة للتنقل بين فرعين تعمل عليهما.
نفّذ أولًا 'git fetch origin'، ثم إما 'git checkout branch-name' (ينشئ Git فرع تتبّع تلقائيًا إن كان origin/branch-name موجودًا) أو صراحةً 'git checkout --track origin/branch-name'.
نعم، استخدم 'git checkout -p <commit> -- <file>' للوضع التفاعلي، أو ببساطة 'git checkout <commit> -- <specific-files>' لاستعادة ملفات معينة فقط من ذلك الـ commit.
لأنه يفعل أمرين مختلفين جدًا: تبديل الفروع واستعادة الملفات. قدّم Git 2.23 الأمرين 'git switch' و'git restore' للفصل بين المهمتين. وما زال 'git checkout' يعمل ويُستخدم على نطاق واسع.