530 Stimmen

Entfernen sensibler Dateien und ihrer Übertragungen aus dem Git-Verlauf

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

Ich weiß, dass ich diese Dateinamen zu .gitignore aber dies würde ihre Geschichte in Git nicht löschen.

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

Gibt es eine Möglichkeit, die alle Spuren einer bestimmten Datei in Ihrem Git-Verlauf?

620voto

natacado Punkte 6173

Für alle praktischen Zwecke ist die erste Worüber Sie sich Sorgen machen sollten, ist ÄNDERN SIE IHRE PASSWÖRTER! Aus Ihrer Frage geht nicht klar hervor, ob Ihr Git-Repository vollständig lokal ist oder ob Sie noch ein entferntes Repository an anderer Stelle haben; wenn es entfernt und nicht vor anderen geschützt ist, haben Sie ein Problem. Wenn jemand das Repository geklont hat, bevor Sie das Problem behoben haben, wird er eine Kopie Ihrer Passwörter auf seinem lokalen Rechner haben, und es gibt keine Möglichkeit, ihn zu zwingen, auf Ihre "behobene" Version zu aktualisieren, wenn diese aus der Geschichte verschwunden ist. Das einzig Sichere, was Sie tun können, ist, Ihr Passwort überall, wo Sie es benutzt haben, in ein anderes zu ändern.


Nachdem das geklärt ist, folgt nun die Lösung des Problems. GitHub hat genau diese Frage in einer FAQ beantwortet :

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

git filter-branch --index-filter \
'git update-index --remove PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

Update 2019:

Dies ist der aktuelle Code aus den FAQ:

  git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" \
  --prune-empty --tag-name-filter cat -- --all
  git push --force --verbose --dry-run
  git push --force

Denken Sie daran, dass Sie, sobald Sie diesen Code in ein entferntes Repository wie GitHub gestellt haben und andere dieses entfernte Repository geklont haben, die Geschichte neu schreiben. Wenn andere versuchen, Ihre letzten Änderungen abzurufen, werden sie eine Meldung erhalten, die besagt, 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 bestehendes Repository löschen und neu klonen oder die Anweisungen unter "WIEDERHERSTELLUNG VON UPSTREAM REBASE" im Git-Rebase-Manpage .

Tipp : Ausführen git rebase --interactive


Wenn Sie in Zukunft versehentlich einige Änderungen mit sensiblen Informationen vornehmen, aber feststellen, dass antes de in ein entferntes Repository zu verschieben, gibt es einige einfachere Korrekturen. Wenn die letzte Übertragung diejenige ist, bei der die sensiblen Informationen hinzugefügt wurden, können Sie die sensiblen Informationen einfach entfernen und dann ausführen:

git commit -a --amend

Dadurch wird die vorherige Übergabe mit allen neuen Änderungen, die Sie vorgenommen haben, ergänzt, einschließlich des Entfernens ganzer Dateien mit einer git rm . Wenn die Änderungen weiter zurückliegen, aber noch nicht in ein entferntes Repository übertragen wurden, können Sie ein interaktives rebase durchführen:

git rebase -i origin/master

Das öffnet einen Editor mit den Commits, die Sie seit Ihrem letzten gemeinsamen Vorfahren mit dem entfernten Repository gemacht haben. Ändern Sie "pick" in "edit" in allen Zeilen, die einen Commit mit sensiblen Informationen darstellen, und speichern und beenden Sie. Git geht die Änderungen durch und lässt Sie an einer Stelle stehen, an der Sie sie bearbeiten können:

$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 gefahrlos veröffentlichen.

143voto

Roberto Tyley Punkte 22905

Das Ändern von Passwörtern ist eine gute Idee, aber für den Prozess des Entfernens von Passwörtern aus der Historie Ihres Repos empfehle ich die BFG Repo-Reiniger , eine schnellere und einfachere Alternative zu git-filter-branch ausdrücklich zum Entfernen privater Daten aus Git-Repos entwickelt.

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

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

Alle Dateien unter einer bestimmten Größe (standardmäßig 1 MB) in der Historie Ihres Repos werden gescannt, und jede übereinstimmende Zeichenkette (die nicht in Ihrem neueste commit) wird durch die Zeichenfolge "***REMOVED***" ersetzt. Sie können dann git gc um die toten Daten zu entfernen:

$ git gc --prune=now --aggressive

Der BFG ist in der Regel 10-50 mal schneller als ein Laufband. git-filter-branch und die Optionen sind vereinfacht und auf diese beiden häufigen Anwendungsfälle zugeschnitten:

  • Entfernen von Verrückt große Dateien
  • Entfernen von Passwörter, Berechtigungsnachweise & Sonstiges Private Daten

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

56voto

Wenn Sie auf GitHub gepusht haben, reicht ein Force Pushing nicht aus, löschen Sie das Repository oder kontaktieren Sie den Support

Selbst wenn Sie eine Sekunde später einen Push erzwingen, reicht dies nicht aus (siehe unten).

Die einzigen zulässigen Vorgehensweisen sind:

  • ist das, was ein veränderbarer Berechtigungsnachweis wie ein Passwort durchsickert?

    • ja: Ändern Sie sofort Ihre Passwörter und erwägen Sie die Verwendung von mehr OAuth- und API-Schlüsseln!

    • nein (Nacktbilder):

      • Macht es Ihnen etwas aus, wenn alle Ausgaben im Repository vernichtet werden?

        • nein: das Repository löschen

        • ja:

          • Kontakt zum Support
          • wenn das Leck für Sie so kritisch ist, dass Sie bereit sind, einige Ausfallzeiten des Endlagers in Kauf zu nehmen, um die Wahrscheinlichkeit eines Lecks zu verringern, es privat machen während Sie darauf warten, dass der GitHub-Support Ihnen antwortet

Es reicht nämlich nicht aus, eine Sekunde später zu drücken:

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

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

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

Siehe auch: Wie entfernt man einen Dangling-Commit von GitHub?

git filter-repo wird jetzt offiziell empfohlen gegenüber git filter-branch

Dies wird in der Manpage von git filter-branch in Git 2.5 selbst.

Mit git filter repo können Sie entweder bestimmte Dateien mit entfernen: Entfernen des Ordners und seines Inhalts aus dem Verlauf von Git/GitHub

pip install git-filter-repo
git filter-repo --path path/to/remove1 --path path/to/remove2 --invert-paths

Dadurch werden leere Commits automatisch entfernt.

Oder Sie können bestimmte Zeichenfolgen durch ersetzen: Wie ersetzt man eine Zeichenkette in einer ganzen Git-Historie?

git filter-repo --replace-text <(echo 'my_password==>xxxxxxxx')

19voto

Jason Goemaat Punkte 27951

Ich empfehle dieses Skript von David Underhill, hat bei mir wunderbar funktioniert.

Es fügt diese Befehle zusätzlich zum natacado-Filterzweig hinzu, um das Chaos zu beseitigen, das er hinterlässt:

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

Vollständiges Skript (alle Angaben von 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
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

Die letzten beiden Befehle funktionieren möglicherweise besser, wenn sie in die folgenden geändert werden:

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

19voto

nachoparker Punkte 1570

Sie können verwenden git forget-blob .

Die Verwendung ist recht einfach git forget-blob file-to-forget . Mehr Informationen erhalten Sie hier

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

Es verschwindet aus allen Übertragungen in Ihrem Verlauf, Reflog, Tags usw.

Ich stoße immer wieder auf das gleiche Problem, und jedes Mal muss ich auf diesen Beitrag und andere zurückkommen, deshalb habe ich den Prozess automatisiert.

Dank der Beiträge von Stack Overflow, die es mir ermöglicht haben, dies zusammenzustellen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X