سؤال

أرغب في وضع مشروع GIT على GitHub ولكنه يحتوي على ملفات معينة ذات بيانات حساسة (أسماء المستخدمين وكلمات المرور ، مثل /config/deploy.rb لـ Capistrano).

أعلم أنه يمكنني إضافة أسماء الملفات هذه إلى .gitignore, ، لكن هذا لن يزيل تاريخهم داخل غيت.

أنا أيضًا لا أريد أن أبدأ من جديد عن طريق حذف دليل /.

هل هناك طريقة لإزالة الكل آثار ملف معين في تاريخ git الخاص بك؟

هل كانت مفيدة؟

المحلول

لجميع الأغراض العملية ، أول الشيء الذي يجب أن تقلق بشأنه هو تغيير كلمات المرور الخاصة بك! ليس من الواضح من سؤالك ما إذا كان مستودع GIT الخاص بك محليًا تمامًا أو ما إذا كان لديك مستودع بعيد في مكان آخر حتى الآن ؛ إذا كانت بعيدة ولم يتم تأمينها من الآخرين ، فأنت تواجه مشكلة. إذا استنساخ أي شخص هذا المستودع قبل إصلاح هذا ، فسيحصل على نسخة من كلمات المرور الخاصة بك على جهازه المحلي ، ولا توجد طريقة لإجباره على التحديث إلى إصدار "ثابت" معه من التاريخ. الشيء الآمن الوحيد الذي يمكنك القيام به هو تغيير كلمة المرور الخاصة بك إلى شيء آخر في كل مكان استخدمته.


مع ذلك بعيدًا ، إليك كيفية إصلاحه. أجاب جيثب على هذا السؤال بالضبط باعتباره الأسئلة الشائعة:

ملاحظة لمستخدمي Windows: استخدم عروض أسعار مزدوجة (") بدلاً من الفردي في هذا الأمر

git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

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

لإصلاح هذا ، سيتعين عليهم إما حذف مستودعهم الحالي وإعادة النقر عليه ، أو اتباع التعليمات تحت "التعافي من Rebase في المنبع" في Git-Rebase Manpage.


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

git commit -a --amend

سيؤدي ذلك إلى تعديل الالتزام السابق بأي تغييرات جديدة قمت بها ، بما في ذلك عمليات إزالة الملفات بأكملها مع أ git rm. إذا كانت التغييرات عادت إلى التاريخ ولكن لا تزال غير مدعومة إلى مستودع بعيد ، فيمكنك القيام بإعادة التفاعل:

git rebase -i origin/master

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

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

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

نصائح أخرى

يعد تغيير كلمات المرور الخاصة بك فكرة جيدة ، ولكن لعملية إزالة كلمة المرور من تاريخ ريبو الخاص بك ، أوصي BFG Repo-Cleaner, بديل أسرع وأبسط عن git-filter-branch مصمم بشكل صريح لإزالة البيانات الخاصة من GIT Repos.

إنشاء private.txt الملف يسرد كلمات المرور ، إلخ ، التي تريد إزالتها (إدخال واحد لكل سطر) ثم قم بتشغيل هذا الأمر:

$ java -jar bfg.jar  --replace-text private.txt  my-repo.git

سيتم فحص جميع الملفات تحت حجم العتبة (1 ميجابايت افتراضيًا) آخر سيتم استبدال الالتزام) بالسلسلة "*** تمت إزالتها ***". يمكنك بعد ذلك الاستخدام git gc لتنظيف البيانات الميتة:

$ git gc --prune=now --aggressive

عادة ما يكون BFG أسرع 10-50x من الركض git-filter-branch ويتم تبسيط الخيارات وتصميمها حول هذين الحالات الشائعة:

  • إزالة ملفات كبيرة مجنونة
  • إزالة كلمات المرور ، بيانات الاعتماد & آخر بيانات خاصة

الإفصاح الكامل: أنا مؤلف كتاب BFG Repo-Cleaner.

انصح هذا السيناريو بقلم ديفيد أندرهيل ، عمل مثل سحر بالنسبة لي.

يضيف هذه الأوامر بالإضافة إلى فرع مرشح Natacado لتنظيف الفوضى التي يتركها وراءها:

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune

السيناريو الكامل (كل الائتمان لديفيد أندرهيل)

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune

قد تعمل الأمرين الأخيرين بشكل أفضل إذا تم تغييرها إلى ما يلي:

git reflog expire --expire=now --all && \
git gc --aggressive --prune=now

إذا دفعت إلى Github ، فإن القوة لا تكون كافية ، قم بحذف المستودع أو دعم الاتصال

حتى لو كنت تجبر الدفع بعد ثانية واحدة ، فهذا لا يكفي كما هو موضح أدناه.

المسارات الوحيدة الصالحة للعمل هي:

  • هل تسرب بيانات اعتماد قابلة للتغيير مثل كلمة المرور؟

    • نعم: قم بتعديل كلمات المرور الخاصة بك على الفور ، وفكر في استخدام المزيد من مفاتيح Oauth و API!
    • لا (صور عارية):

      • هل تهتم إذا حصلت جميع المشكلات في المستودع على قناة نووية؟

        • لا: حذف المستودع
        • نعم:

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

إن دفع دفع ثانية في وقت لاحق لا يكفي لأن:

إذا قمت بحذف المستودع بدلاً من مجرد قوة الدفع ، فإن الالتزامات تختفي حتى من واجهة برمجة التطبيقات على الفور وتعطي 404 ، على سبيل المثال https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2d653f7a3824 هذا يعمل حتى لو قمت بإعادة إنشاء مستودع آخر بنفس الاسم.

لاختبار هذا ، قمت بإنشاء ريبو: https://github.com/cirosantilli/test-dangling و فعل:

git init
git remote add origin git@github.com:cirosantilli/test-dangling.git

touch a
git add .
git commit -m 0
git push

touch b
git add .
git commit -m 1
git push

touch c
git rm b
git add .
git commit --amend --no-edit
git push -f

أنظر أيضا: كيفية إزالة الالتزام المتدلي من جيثب؟

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

سيكون بديل:

  1. قرص مضغوط إلى فرع الأساس للمشروع
  2. قم بإزالة الكود / الملف الحساس
  3. RM -RF .GIT/ # قم بإزالة جميع معلومات GIT من التعليمات البرمجية الخاصة بك
  4. انتقل إلى github وحذف مستودعك
  5. اتبع هذا الدليل لدفع الكود الخاص بك إلى مستودع جديد كما تفعل عادة -https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

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

نسمي هذا الخيار النووي.

هذا هو الحل في Windows

GIT Filter-Branch-TREE-FILTER "RM -F 'Filedir/Filename" "Head"

دفع GIT -قوة

تأكد من أن المسار صحيح وإلا فلن يعمل

اتمني ان يكون مفيدا

يستخدم تصفية الفرع:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *file_path_relative_to_git_repo*' --prune-empty --tag-name-filter cat -- --all

git push origin *branch_name* -f

يمكنك استخدام git forget-blob.

الاستخدام بسيط جدا git forget-blob file-to-forget. يمكنك الحصول على مزيد من المعلومات هنا

https://ownyourbits.com/2017/01/18/completely-remove-a-file-file-from-a-git-repository-with-git-forget-blob/

سوف تختفي من كل الاشتراكات في تاريخك ، والعلامات ، وما إلى ذلك

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

اعتمادات للمساهمين من Stack Overflow التي سمحت لي بوضع هذا معًا

اضطررت للقيام بذلك عدة مرات حتى الآن. لاحظ أن هذا يعمل فقط على ملف واحد في وقت واحد.

  1. احصل على قائمة بجميع الالتزامات التي قامت بتعديل الملف. واحد في الأسفل سوف الالتزام الأول:

    git log --pretty=oneline --branches -- pathToFile

  2. لإزالة الملف من السجل ، استخدم الالتزام الأول SHA1 ومسار الملف من الأمر السابق ، وملءه في هذا الأمر:

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..

لذلك ، يبدو شيئًا كهذا:

git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

إزالة ذاكرة التخزين المؤقت للملف المسار من git وأضف هذا الملف إلى .gitignore قائمة

في مشروع Android الخاص بي كان لدي addob_keys.xml كما منفصل ملف XML في APP/SRC/MAIN/RES/DAWER مجلد. لإزالة هذا الملف الحساس الذي استخدمته أدناه البرنامج النصي وعملت بشكل مثالي.

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch  app/src/main/res/values/admob_keys.xml' \
--prune-empty --tag-name-filter cat -- --all
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top