file-io كيفية - البحث عن واستعادة ملف محذوف في مستودع Git




استرجاع عربي (17)

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

أعلم أنه يمكنني git checkout HEAD^ foo.bar أحد الملفات باستخدام git checkout HEAD^ foo.bar ، ولكن لا أعرف حقًا متى تم حذف هذا الملف.

  1. ما هي أسرع طريقة للعثور على الالتزام الذي حذف اسم ملف معين؟
  2. ما هي أسهل طريقة لإعادة هذا الملف إلى نسخة العمل الخاصة بي؟

آمل ألا أحتاج إلى تصفح سجلاتي يدويًا ، أو التحقق من المشروع بأكمله من أجل SHA معيّن ، ثم نسخ هذا الملف يدويًا في تسجيلي الأصلي للمشروع.


Answers

ابحث عن الالتزام الأخير الذي أثر على المسار المحدد. نظرًا لأن الملف ليس في الالتزام HEAD ، يجب أن يكون هذا الالتزام قد حذفه.

git rev-list -n 1 HEAD -- <file_path>

ثم الخروج من الإصدار في الالتزام من قبل ، باستخدام الرمز الإقحام ( ^ ):

git checkout <deleting_commit>^ -- <file_path>

أو في أمر واحد ، إذا كان $file هو الملف المعني.

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

إذا كنت تستخدم zsh وتم تمكين الخيار EXTENDED_GLOB ، لن يعمل رمز الإقحام. يمكنك استخدام ~1 بدلاً من ذلك.

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"

لاستعادة ملف محذوف و ملتزم:

git reset HEAD some/path
git checkout -- some/path

تم اختباره على إصدار Git 1.7.5.4.


إذا كنت تعرف اسم الملف ، فهذه طريقة سهلة باستخدام الأوامر الأساسية:

أدرج جميع الإلتزامات الخاصة بهذا الملف.

git log -- path/to/file

آخر التزام (الأعلى) هو الذي قام بحذف الملف. لذلك تحتاج لاستعادة الثانية إلى آخر ارتكاب.

git checkout {second to last commit} -- path/to/file

إذا كنت مجنونًا ، فاستخدم git-bisect . إليك ما يجب فعله:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

الآن حان الوقت لتشغيل الاختبار الآلي. '[ -e foo.bar ]' الأمر shell '[ -e foo.bar ]' 0 إذا كان foo.bar موجودًا ، و 1 بخلاف ذلك. سيستخدم أمر "تشغيل" git-bisect بحثًا ثنائيًا للعثور تلقائيًا على الالتزام الأول حيث فشل الاختبار. ويبدأ في منتصف الطريق من خلال النطاق المعطى (من الجيد إلى السيئ) ويقطعه إلى النصف بناءً على نتيجة الاختبار المحدد.

git bisect run '[ -e foo.bar ]'

أنت الآن في الالتزام الذي حذفها. من هنا ، يمكنك الرجوع إلى المستقبل واستخدام git-revert للتراجع عن التغيير ،

git bisect reset
git revert <the offending commit>

أو يمكنك العودة إلى ارتكاب واحد وفحص الضرر يدويًا:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

بسيطة ودقيقة

أولاً ، احصل على آخر التزام ثابت يكون لديك هذا الملف من خلاله -

git log 

لنفترض أنك عثرت على $ commitid 1234567 ... ،

git checkout <$commitid> $fileName

سيؤدي ذلك إلى استعادة إصدار الملف الذي كان في هذا الالتزام.


$ git log --diff-filter=D --summary  | grep "delete" | sort

إذا كنت تعرف الالتزام الذي حذف الملف (الملفات) ، <SHA1_deletion> بتشغيل هذا الأمر حيث <SHA1_deletion> هو الالتزام الذي حذف الملف:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

يسرد الجزء الموجود قبل توجيه الإخراج كافة الملفات التي تم حذفها في الالتزام؛ انهم جميعا الخروج من الالتزام السابق لاستعادتها.


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

استنادًا إلى إجابة تشارلز بيلي الرائعة هنا ،

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)

لاستعادة كل تلك الملفات المحذوفة في مجلد ، أدخل الأمر التالي.

git ls-files -d | xargs git checkout --

لدي هذا الحل

  1. احصل على معرف الالتزام حيث تم حذف الملف باستخدام إحدى الطرق أدناه.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* git log --stat | grep --context=5 *word* # recommended إذا كنت نادراً ما تتذكر أي شيء
  2. يجب أن تحصل على شيء مثل:

ارتكاب bfe68bd117e1091c96d2976c99b3bcc8310bebe7 المؤلف: ألكسندر أورلوف التاريخ: الخميس 12 مايو 23:44:27 2011 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

ارتكب 3ea4e3af253ac6fd1691ff6bb89c964f54802302 المؤلف: ألكسندر أورلوف التاريخ: الخميس 12 مايو 22:10:22 2011 +0200

3 . الآن باستخدام ملف الالتزام bfe68bd117e1091c96d2976c99b3bcc8310bebe7:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

نظرًا لأن معرف الالتزام يشير إلى الالتزام حيث تم حذف الملف بالفعل ، يلزمك الإشارة إلى الالتزام قبل bfe68b فقط والذي يمكنك فعله بإلحاق ^1 . هذا يعني: أعطني الالتزام قبل bfe68b.


اسمي المفضل الجديد ، استنادًا إلى answer bonyiii (upvoted) ، وإجابتي الخاصة حول " تمرير حجة إلى أمر git alias ":

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

لقد فقدت ملفًا ، تم حذفه عن طريق الخطأ قبل ارتكاب بعض الأخطاء؟
بسرعة:

git restore my_deleted_file

تفادت الأزمة.

يقترح روبرت دايلي في التعليقات الاسم المستعار التالي:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

ويضيف jegan في التعليقات :

لإعداد الاسم المستعار من سطر الأوامر ، استخدمت هذا الأمر:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

git undelete path/to/file.ext

  1. ضع هذا في .bash_profile (أو أي ملف آخر ذي صلة يتم تحميله عند فتح shell أمر):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. ثم استخدام:

    git undelete path/to/file.ext
    

يتحقق هذا الاسم المستعار أولاً للعثور على آخر التزام حيث يوجد هذا الملف ، ثم يقوم git الخروج من مسار هذا الملف من هذا الالتزام الأخير حيث يوجد هذا الملف. source


إذا قمت بإجراء تغييرات وحذف ملفًا فقط ، ولكنك لم تقم بإلزامه ، والآن قمت بفك التغييرات

git checkout -- .

ولكن لم يتم إرجاع الملفات المحذوفة ، فأنت تفعل الأمر التالي ببساطة:

git checkout <file_path>

و المعزوفة ، عاد ملفك.


  1. استخدم git log --diff-filter=D --summary للحصول على كل git log --diff-filter=D --summary التي حذف الملفات والملفات المحذوفة ؛
  2. استخدم git checkout $commit~1 filename لاستعادة الملف المحذوف.

حيث أن $commit هو قيمة الالتزام الذي وجدته في الخطوة 1 ، على سبيل المثال e4cf499627


لدي نفس السؤال. دون معرفة ذلك ، كنت قد خلقت التزام متدلي .

قائمة التعلق التعلق

git fsck --lost-found

فحص كل التزام متدلي

git reset --hard <commit id>

ظهرت الملفات الخاصة بي عندما انتقلت إلى الالتزام المتدلي.

git status للسبب:

“HEAD detached from <commit id where it detached>”



إذا كنت فوضى شيء داخل git rebase ، على سبيل المثال git rebase --abort ، في حين أن لديك ملفات غير ملتزم بها ، سيتم فقدانها و git reflog لن يساعد. حدث هذا لي وسوف تحتاج إلى التفكير خارج المربع هنا. إذا كنت محظوظاً مثلي واستخدام IntelliJ Webstorm ، فيمكنك النقر right-click->local history ، ويمكنك العودة إلى حالة سابقة من الملفات / المجلدات الخاصة بك بغض النظر عن الأخطاء التي قمت بها مع برنامج إصدار. من الجيد دائمًا أن يكون هناك تشغيل آمن آخر.





git file-io git-checkout