wake-up-neo.net

Entfernen Sie vertrauliche Dateien und deren Commits aus dem Git-Verlauf

Ich möchte ein Git-Projekt auf GitHub einfügen, aber es enthält bestimmte Dateien mit vertraulichen Daten (Benutzernamen und Kennwörter wie /config/deploy.rb für capistrano).

Ich weiß, dass ich diese Dateinamen zu .gitignore hinzufügen kann, aber dies würde ihren Verlauf in Git nicht entfernen.

Ich möchte auch nicht noch einmal von vorne anfangen, indem ich das Verzeichnis /.git lösche.

Gibt es eine Möglichkeit, all traces einer bestimmten Datei in Ihrem Git-Verlauf zu entfernen?

298
Stefan

Für alle praktischen Zwecke ist das erste , worüber Sie sich Sorgen machen sollten, ÄNDERN IHRER PASSWÖRTER! Ist es nicht Aus Ihrer Frage geht klar hervor, ob Ihr Git-Repository vollständig lokal ist oder ob Sie bereits ein Remote-Repository an einem anderen Ort haben. Wenn es entfernt und nicht vor anderen geschützt ist, liegt ein Problem vor. Wenn jemand dieses Repository geklont hat, bevor Sie dieses Problem behoben haben, verfügt er über eine Kopie Ihrer Kennwörter auf seinem lokalen Computer, und Sie können ihn auf keinen Fall zwingen, auf Ihre "feste" Version zu aktualisieren, wenn diese aus der Vergangenheit stammt. Das einzig sichere, was Sie tun können, ist, Ihr Passwort überall dort in ein anderes zu ändern, wo Sie es verwendet haben.


Hier erfahren Sie, wie Sie das Problem beheben können. GitHub hat genau diese Frage als FAQ beantwortet :

Hinweis für Windows-Benutzer : Verwenden Sie in diesem Befehl doppelte Anführungszeichen (") anstelle von Singles

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

Denken Sie daran, dass Sie sich jetzt in einer Situation befinden, in der Sie den Verlauf umschreiben, wenn Sie diesen Code in ein Remote-Repository wie GitHub verschoben haben und andere das Remote-Repository geklont haben. Wenn andere Benutzer danach versuchen, Ihre letzten Änderungen abzurufen, wird eine Meldung angezeigt, dass die Änderungen nicht übernommen werden können, da es sich nicht um einen Schnellvorlauf handelt.

Um dies zu beheben, müssen sie entweder ihr vorhandenes Repository löschen und erneut klonen oder den Anweisungen unter "WIEDERHERSTELLEN VON UPSTREAM REBASE" in der Manpage Git-Rebase folgen.


Wenn Sie in Zukunft versehentlich Änderungen an vertraulichen Informationen vornehmen, jedoch feststellen, dass bevor auf ein Remote-Repository verschoben wird, gibt es einige einfachere Korrekturen. Wenn Sie zuletzt die vertraulichen Informationen hinzugefügt haben, können Sie die vertraulichen Informationen einfach entfernen und dann ausführen:

git commit -a --amend

Dadurch wird das vorherige Commit durch alle neuen Änderungen geändert, einschließlich der vollständigen Dateientfernungen, die mit einem git rm durchgeführt wurden. Wenn die Änderungen im Verlauf weiter zurückliegen, aber immer noch nicht in ein Remote-Repository verschoben wurden, können Sie eine interaktive Rebase durchführen:

git rebase -i Origin/master

Dadurch wird ein Editor mit den Festschreibungen geöffnet, die Sie seit Ihrem letzten gemeinsamen Vorfahren mit dem Remote-Repository vorgenommen haben. Ändern Sie "Auswählen" in "Bearbeiten" in allen Zeilen, die einen Commit mit vertraulichen Informationen darstellen, und speichern und beenden Sie ihn. Git wird die Änderungen durchgehen und Sie an einem Ort zurücklassen, an dem Sie:

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

Für jede Änderung mit sensiblen Informationen. Schließlich landen Sie wieder in Ihrem Zweig, und Sie können die neuen Änderungen sicher übertragen.

398
natacado

Das Ändern Ihrer Passwörter ist eine gute Idee, aber für das Entfernen von Passwörtern aus dem Verlauf Ihres Repos empfehle ich den BFG Repo-Cleaner , eine schnellere und einfachere Alternative zu git-filter-branch, die explizit zum Entfernen privater Daten aus Git-Repos entwickelt wurde.

Erstellen Sie eine private.txt-Datei mit den Passwörtern usw., die Sie entfernen möchten (ein Eintrag pro Zeile), und führen Sie dann den folgenden Befehl aus:

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

Alle Dateien mit einer Schwellenwertgröße (standardmäßig 1 MB) im Verlauf Ihres Repos werden gescannt, und alle übereinstimmenden Zeichenfolgen (die nicht in latest commit sind) werden durch die Zeichenfolge "*** REMOVED" ersetzt *** ". Sie können dann git gc verwenden, um die toten Daten zu entfernen:

$ git gc --Prune=now --aggressive

Das BFG ist normalerweise um das 10- bis 50-fache schneller als git-filter-branch, und die Optionen sind vereinfacht und auf diese zwei häufigen Anwendungsfälle zugeschnitten:

  • Crazy Big Files entfernen
  • Entfernen von Passwörtern, Anmeldeinformationen und anderen privaten Daten

Vollständige Offenlegung: Ich bin der Autor des BFG Repo-Cleaners.

71
Roberto Tyley

Ich empfehle dieses Skript von David Underhill, das für mich wie ein Zauber wirkt. 

Sie fügt diese Befehle zusätzlich zum Filterzweig von natacado hinzu, um das durch sie hinterlassene Chaos zu beseitigen:

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

Vollständiges Skript (alle Gutschriften an David Underhill)

#!/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
[email protected]
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

Die letzten beiden Befehle funktionieren möglicherweise besser, wenn sie wie folgt geändert werden:

git reflog expire --expire=now --all && \
git gc --aggressive --Prune=now
17
Jason Goemaat

Wenn Sie bereits auf GitHub gepusht haben, sind die Daten gefährdet, selbst wenn Sie sie zwingen, sie eine Sekunde später wegzuschieben, weil:

Um dies zu testen, habe ich ein Repo erstellt: https://github.com/cirosantilli/test-dangling und fertig:

git init
git remote add Origin [email protected]: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

Wenn Sie das Repository löschen, verschwinden Commits jedoch auch sofort aus der API und geben 404, z. https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 } Dies funktioniert auch, wenn Sie ein anderes Repository mit demselben Namen erstellen.

Meine empfohlene Vorgehensweise ist also:

  • Ändern Sie Ihre Anmeldeinformationen

  • wenn das nicht reicht (z. B. nackte Bilder):

    • löschen Sie das Repository
    • kontaktieren Sie Support

Um es klar zu sagen: Die akzeptierte Antwort ist richtig. Versuchen Sie es zuerst. Für einige Anwendungsfälle kann dies jedoch unnötig komplex sein, insbesondere wenn Sie störende Fehler wie "fatal: bad revision --Prune-empty" feststellen oder sich nicht wirklich um die Historie Ihres Repos kümmern.

Eine Alternative wäre:

  1. cD zum Basiszweig des Projekts 
  2. Entfernen Sie den vertraulichen Code/die Datei
  3. rm -rf .git/# Entfernen Sie alle Git-Informationen aus Ihrem Code 
  4. Gehen Sie zu github und löschen Sie Ihr Repository
  5. Befolgen Sie diese Anleitung, um Ihren Code wie üblich in ein neues Repository zu verschieben. - https://help.github.com/articles/adding-an-existing-project-to-github- using-the- Befehlszeile/

Dadurch werden natürlich alle Verzweigungsprotokollzweige und Probleme sowohl von Ihrem Github-Repo als auch von Ihrem lokalen Git-Repo entfernt. Wenn dies nicht akzeptabel ist, müssen Sie einen alternativen Ansatz verwenden.

Nennen wir dies die nukleare Option.

8
lostphilosopher

Hier ist meine Lösung in Windows

git filter-branch - Baum-Filter "rm -f 'filedir/filename"

git Push --force

stellen Sie sicher, dass der Pfad korrekt ist Andernfalls funktioniert er nicht

Ich hoffe, es hilft

6
vertigo71

Verwenden Sie filter-branch :

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

Sie können git forget-blob verwenden.

Die Verwendung ist ziemlich einfach git forget-blob file-to-forget. Weitere Informationen erhalten Sie hier

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

Es verschwindet aus allen Commits in Ihrem Protokoll, dem Reflog, den Tags usw.

Ich stelle ab und zu das gleiche Problem auf und jedes Mal, wenn ich zu diesem Post und anderen zurückkehren muss, habe ich den Prozess automatisiert.

Dank an Mitwirkende von Stack Overflow, die es mir ermöglichten, dies zusammenzustellen

4
nachoparker

Ich musste das bisher ein paar Mal machen. Beachten Sie, dass dies nur für eine Datei gleichzeitig funktioniert.

  1. Liefert eine Liste aller Commits, die eine Datei geändert haben. Die unterste wird die erste Festschreibung:

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

  2. Um die Datei aus dem Verlauf zu entfernen, verwenden Sie den ersten Commit sha1 und den Pfad zur Datei des vorherigen Befehls und geben Sie diesen in den folgenden Befehl ein:

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

2
b01

So sieht es ungefähr so ​​aus:

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

Entfernen Sie den Cache für die verfolgte Datei aus git und fügen Sie diese Datei zur .gitignore-Liste hinzu

2
przbadu

In meinem Android-Projekt hatte ich admob_keys.xml als getrennte XML-Datei im Ordner app/src/main/res/values ​​/ . Um diese sensible Datei zu entfernen, habe ich das folgende Skript verwendet und einwandfrei gearbeitet.

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
0
Ercan Duman