العودة إلى المدونة

خطأ fatal: not a git repository: الإصلاح في 60 ثانية

28 سبتمبر 2026

هل حلّ هذا المشكلة؟

أسرع طريق لتضييع عشرين دقيقة: كتابة git pull في المجلد الأب لمستودعك. يرد Git بـ‏fatal: not a git repository (or any of the parent directories): .git، وأكثر الإجابات على الشبكة تكمل بـ‏git init — وهو خطأ في ثلاثة من الأسباب الأربعة الحقيقية.

الفرز في 60 ثانية:

git rev-parse --show-toplevel || ls -a

عند وجود مستودع فوقك يطبع --show-toplevel جذر المستودع — مجلد خطأ، قضية مغلقة، cd وانتهى. وإذا فشل هو أيضًا، فالسطر نفسه يسرد محتويات المجلد: لا .git في تلك القائمة يعني لم يوجد هنا مستودع يُجد أصلًا. هذا الأمر وحده يفصل بين السببين وراء معظم الحالات. بقية المقال للحالات الأندر.

لماذا يقول Git ‏«fatal: not a git repository»؟

يجد Git المستودع بالصعود من المجلد الحالي بحثًا عن مدخل .git، ويتوقف عند الأول. ينكسر هذا الصعود بأربع طرق بالضبط: أنت خارج الشجرة، أو اختفى مجلد .git، أو أن متغير بيئة حوّل البحث عن مساره، أو أن .git موجود لا يشير إلى شيء. وفق استطلاع Stack Overflow لعام 2022 يعمل Git على نحو 94% من أجهزة المطورين، فالخطأ طقس جماعي عابر. تعلّم الحالات الأربع مرة واحدة فتتوقف عن كلفك وقتًا.

(إن كان مستودعك سليمًا وكنت جاءت أصلك لتتراجع عن commit، فصفحة Undo Anything in Git تجمع كل مسارات الإصلاح في هذا الموقع بمكان واحد.)

الحالة 1: أنت في المجلد الخطأ

الأشيع. صورتان:

  1. نفّذت cd إلى مجلد فرعي — docs/ أو src/api/ — وعادةً من مشروع آخر تقول لك إن الجذر هنا. يصعد Git فلا يجد شيئًا، فيستسلم.
  2. استنسخت مستودعًا وتوقعت الملفات هنا، لكن git clone ينشئ دائمًا مجلدًا فرعيًا باسم المستودع. فالـcheckout يقبع مستوى أدنى من موقفك.
git rev-parse --show-toplevel   # يطبع الجذر عند وجوده
cd "$(git rev-parse --show-toplevel)"  # اقفز إليه بأمر واحد

الأمر الثاني يحل مشكلة الذاكرة العضلية إلى الأبد: يعمل من أي عمق داخل المستودع.

الحالة 2: لا يوجد .git — المجلد لم يكن مستودعًا قط

ls -a لا يُظهر .git. عادةً أحد هذه:

  • ملف ZIP من GitHub. ‏Code → Download ZIP يسلّم الملفات وحدها: لا .git ولا تاريخ ولا remote. وتوثيق GitHub يؤكد أن أرشيف ZIP لا يحوي إلا لقطة الشيفرة.
  • ملفات منسوخة من جهاز أو مشروع آخر، بلا المجلد الخفي.
  • أداة تنظيف حذفت .git على أنه «مجلد خفي بلا فائدة».

الإصلاح: أعِد الاستنساخ لتستعيد التاريخ.

cd ..
git clone https://github.com/<user>/<repo>.git

يبدأ git init هنا مستودعًا جديدًا كليًا؛ لا يُسترد شيء. وكومة الملفات المنسوخة عادةً ما تجر ملفات غير متتبعة معها؛ صفحة git remove untracked files تغطي التنظيف بعد استقرار النسخة المستنسخة.

git init لا يُصلح مستودعًا — بل ينشئ واحدًا فارغًا حيث تقف.

الحالة 3: ‏GIT_DIR مُصدَّر فيكسر كل المستودعات

الدليل: الخطأ يلاحقك إلى مجلدات كان Git يعمل فيها قبل ساعة. ‏GIT_DIR المُصدَّر يأمر Git بالنظر إلى مسار ثابت بدل اكتشاف المستودع، فيصير كل مجلد «عادي» ‏«not a repository».

env | grep GIT_DIR     # GIT_DIR=/مسار/قديم
unset GIT_DIR

إن عاد كل صباح، فسطرٌ في ~/.bashrc أو ~/.zshrc أو غلاف CI يُصدّره. أنظمة CI تضبط GIT_DIR عمدًا: صحيح داخل خط الأنابيب، لغم في الـshell التفاعلي.

الحالة 4: الـsubmodule لم يُهيَّأ قط

تدخل إلى vendor/libfoo/، فيقول Git إن المجلد ليس مستودعًا. وهو صادق: قبل التهيئة يكون مجلد الـsubmodule مجلدًا فارغًا بسطر في .gitmodules وبلا أي checkout.

cat .gitmodules        # يسرد مسارات الـsubmodules
git submodule update --init --recursive

نفّذه من جذر المستودع لا من داخل الـsubmodule — قاعدة الصعود تنطبق، والـsubmodule الفارغ لا جذر يُصعد إليه.

الحالة 5: ‏.git ملف، وهدفه اختفى

تحوّل الـworktrees والـsubmodules‏ .git إلى ملف من سطر واحدة: ‏gitdir: /المسار/إلى/gitdir/الحقيقي. حين يُحذف الـgitdir الحقيقي (تنظيف .git/modules أو قرص منقول)، يعلق المؤشر فيجد الصاعد .git لا يجيب عن شيء:

$ ls -la .git
-rw-r--r-- 1 you you 35 Sep 28 10:12 .git     # ملف، لا مجلد
$ cat .git
gitdir: ../.git/modules/libfoo
git worktree repair    # يعيد ربط الـworktrees التي تغيّرت مساراتها

إن لم يجد worktree repair الهدف فالـgitdir ضاع. وتاريخ الـsubmodules يسكن في .git/modules/<الاسم> للمستودع الأب؛ تحقق من وجوده قبل الحكم بأسوأ احتمال.

العرَض ← السبب ← الإصلاح

العرَضالسبب المرجحالإصلاح
خطأ في مشروع واحد وls -a بلا .gitZIP منزّل / ملفات منسوخةgit clone من جديد
خطأ من مجلد فرعي والجذر يعملخارج الشجرةcd "$(git rev-parse --show-toplevel)"
خطأ في كل المجلدات حتى التي كانت تعملGIT_DIR مُصدَّرunset GIT_DIR وتنقيته من ملف الـshell
خطأ داخل مجلد submodulesubmodule غير مهيأgit submodule update --init --recursive
‏.git ملف والخطأ مستمرمؤشر worktree/submodule معلّقgit worktree repair، وإلا أعد الاستنساخ

هل يكون git init هو الإصلاح الصحيح يومًا؟

مرة واحدة: حين لا يُظهر ls -a أي .git وتنوي فتح مستودع جديد هنا هنا. نفّذه، والأمر التالي يكون git add لا git log.

في كل موضع آخر هو فخ موقّع. ‏git init في مجلد أعمق بمستوى يبني مستودعًا متداخلًا بلا أي commit — ويرد git log التالي بـ‏fatal: your current branch 'main' does not have any commits yet. هذا الخطأ يعني أنك أنشأت للتو مستودعًا حيث تقف، والحقيقي مستوى فوقك. والتنظيف جراحي:

cd المجلد-المتداخل
rm -rf .git    # يحذف المستودع العرضي فقط، الملفات سليمة

دقّق في السطر قبل ذلك rm: يجب أن يعمل داخل المجلد المتداخل، لا عند جذر المشروع أبدًا. ثم cd إلى الجذر الحقيقي وتأكد بـ‏git rev-parse --show-toplevel أن Git يعثر على ما كان ينبغي أن يجده منذ البداية.

FAQ

لماذا يقول git status ‏fatal: not a git repository؟

يبحث Git عن مجلد .git في المجلد الحالي ثم في كل الأصول. لا يوجد .git في أي درجة من الشجرة يعني لا توجد مستودع — غالبًا أنت في المجلد الخطأ، أو وصل المشروع بلا تاريخه.

هل يُصلح git init خطأ fatal: not a git repository؟

فقط حيث لم يوجد مستودع أصلًا. ‏init ينشئ مستودعًا جديدًا فارغًا عاجزًا عن استرداد أي تاريخ من مكان آخر. نفّذه في مجلد أعمق بمستوى وستحصل على مستودع متداخل بلا أي commit.

كيف أصلح الخطأ داخل submodule؟

من جذر المستودع: git submodule update --init --recursive. يبقى مجلد الـsubmodule فارغًا حتى ذلك الحين، ويعلنه Git ‏not a repository.

لماذا يظهر الخطأ في كل مستودعات الجهاز؟

متغير GIT_DIR المُصدَّر يتجاوز اكتشاف المستودعات في كل مكان. نفّذ env | grep GIT_DIR ثم unset GIT_DIR — واحذفه من ملف تعريف الـshell إن كان يعود.

— mrsaynothing

$ احصل على الشرح التطبيقي التالي بالبريد

رسالة واحدة لكل مقال. أصلح المشكلة وامضِ.

self-hosted · بلا أطراف ثالثة · إلغاء الاشتراك بنقرة واحدة

ما هذا؟