Wie können Sie eine fehlerhafte Zusammenführung beheben und Ihre guten Commits auf eine feste Zusammenführung übertragen?

407

Ich filename.orighabe vor einigen Commits versehentlich eine unerwünschte Datei ( beim Auflösen einer Zusammenführung) in mein Repository übernommen, ohne dass ich es bisher bemerkt habe. Ich möchte die Datei vollständig aus dem Repository-Verlauf löschen.

Ist es möglich, den Änderungsverlauf so umzuschreiben, dass er überhaupt filename.orignicht zum Repository hinzugefügt wurde?

Grant Limberg
quelle

Antworten:

297

Bitte verwenden Sie dieses Rezept nicht, wenn Ihre Situation nicht der in der Frage beschriebenen entspricht. Dieses Rezept dient zum Beheben einer schlechten Zusammenführung und zum Wiederholen Ihrer guten Commits für eine feste Zusammenführung.

Obwohl filter-branches tun wird, was Sie wollen, ist es ein ziemlich komplexer Befehl, und ich würde mich wahrscheinlich dafür entscheiden, dies zu tun git rebase. Es ist wahrscheinlich eine persönliche Präferenz. filter-branchDies kann in einem einzigen, etwas komplexeren Befehl ausgeführt werden, während die rebaseLösung die entsprechenden logischen Operationen Schritt für Schritt ausführt.

Probieren Sie das folgende Rezept:

# create and check out a temporary branch at the location of the bad merge
git checkout -b tmpfix <sha1-of-merge>

# remove the incorrectly added file
git rm somefile.orig

# commit the amended merge
git commit --amend

# go back to the master branch
git checkout master

# replant the master branch onto the corrected merge
git rebase tmpfix

# delete the temporary branch
git branch -d tmpfix

(Beachten Sie, dass Sie eigentlich keinen temporären Zweig benötigen. Sie können dies mit einem 'getrennten HEAD' tun. Sie müssen jedoch die Commit-ID notieren, die durch den git commit --amendSchritt generiert wurde , um den git rebaseBefehl bereitzustellen, anstatt den temporären Zweig zu verwenden Name.)

CB Bailey
quelle
6
Wäre das nicht git rebase -ischneller und trotzdem so einfach? $ git rebase -i <sh1-of-merge> Markiere das richtige als "edit" $ git rm somefile.orig $ git commit --amend $ git rebase --continue Aus irgendeinem Grund habe ich diese Datei jedoch immer noch irgendwo als letzte Mal habe ich das gemacht. Vermutlich fehlt etwas.
Wernight
12
git rebase -iDies ist sehr nützlich, insbesondere wenn Sie mehrere Rebase-Operationen ausführen müssen. Es ist jedoch richtig, genau zu beschreiben, wenn Sie nicht tatsächlich über die Schulter einer Person zeigen und sehen können, was diese mit ihrem Editor tut. Ich benutze vim, aber nicht jeder würde sich freuen mit: "ggjcesquash <Esc> jddjp: wq" und Anweisungen wie "Verschiebe die oberste Zeile nach der aktuellen zweiten Zeile und ändere das erste Wort in Zeile vier in" Bearbeiten ", speichere jetzt und quit "scheint schnell komplexer zu sein als die eigentlichen Schritte. Normalerweise haben Sie auch einige --amendund --continueAktionen.
CB Bailey
3
Ich habe dies getan, aber ein neues Commit wurde zusätzlich zu dem geänderten mit derselben Nachricht erneut angewendet. Anscheinend hat git eine 3-Wege-Zusammenführung zwischen dem alten, nicht geänderten Commit, das die unerwünschte Datei enthält, und dem festen Commit aus dem anderen Zweig durchgeführt, und so hat es ein neues Commit über dem alten erstellt, um die Datei erneut anzuwenden.
6
@UncleCJ: Wurde Ihre Datei in einem Merge-Commit hinzugefügt? Das ist wichtig. Dieses Rezept wurde entwickelt, um mit einem schlechten Zusammenführungs-Commit fertig zu werden. Es wird nicht funktionieren, wenn Ihre unerwünschte Datei in einem normalen Commit im Verlauf hinzugefügt wurde.
CB Bailey
1
Ich bin erstaunt, wie ich das alles mit Smartgit und ohne Terminal machen kann! Danke für das Rezept!
Cregox
209

Einführung: Sie haben 5 Lösungen zur Verfügung

Das Originalplakat besagt:

Ich habe versehentlich eine unerwünschte Datei festgeschrieben ... vor einigen Festschreibungen in mein Repository ... Ich möchte die Datei vollständig aus dem Repository-Verlauf löschen.

Ist es möglich, den Änderungsverlauf so umzuschreiben, dass er überhaupt filename.orignicht zum Repository hinzugefügt wurde?

Es gibt viele verschiedene Möglichkeiten, den Verlauf einer Datei vollständig aus git zu entfernen:

  1. Commits ändern.
  2. Hard Resets (möglicherweise plus Rebase).
  3. Nicht interaktive Rebase.
  4. Interaktive Rebases.
  5. Filtern von Zweigen.

Im Fall des Originalplakats ist die Änderung des Commits für sich genommen keine Option, da er anschließend mehrere zusätzliche Commits vorgenommen hat. Der Vollständigkeit halber werde ich jedoch auch erklären, wie dies für alle anderen zu tun ist, die es nur wollen ihre vorherige Verpflichtung zu ändern.

Beachten Sie, dass bei all diesen Lösungen der Verlauf / die Commits auf eine andere Weise geändert / neu geschrieben werden müssen . Daher muss jeder Benutzer mit alten Kopien der Commits zusätzliche Arbeit leisten, um seinen Verlauf mit dem neuen Verlauf neu zu synchronisieren.


Lösung 1: Ändern von Commits

Wenn Sie in Ihrem vorherigen Commit versehentlich eine Änderung vorgenommen haben (z. B. das Hinzufügen einer Datei) und der Verlauf dieser Änderung nicht mehr vorhanden sein soll, können Sie das vorherige Commit einfach ändern, um die Datei daraus zu entfernen:

git rm <file>
git commit --amend --no-edit

Lösung 2: Hard Reset (möglicherweise plus Rebase)

Wie bei Lösung Nr. 1 haben Sie auch die Möglichkeit, einfach einen Hard-Reset für das übergeordnete Element durchzuführen, wenn Sie nur Ihr vorheriges Commit entfernen möchten:

git reset --hard HEAD^

Dieser Befehl wird schwer zurückzusetzen Zweig zum vorherigen 1 st Eltern begehen.

Allerdings mit einem Fütterungsmaterial, wenn, wie das ursprüngliche Plakat, haben Sie mehrere Commits gemacht nach dem Commit Sie die Änderung rückgängig machen möchten, können Sie immer noch schwer Resets verwendenihn zu ändern, sondern beinhaltet auch so tun. Hier sind die Schritte, mit denen Sie ein Commit weiter hinten in der Geschichte ändern können:

# Create a new branch at the commit you want to amend
git checkout -b temp <commit>

# Amend the commit
git rm <file>
git commit --amend --no-edit

# Rebase your previous branch onto this new commit, starting from the old-commit
git rebase --preserve-merges --onto temp <old-commit> master

# Verify your changes
git diff master@{1}

Lösung 3: Nicht interaktive Wiederherstellung

Dies funktioniert, wenn Sie nur ein Commit vollständig aus dem Verlauf entfernen möchten:

# Create a new branch at the parent-commit of the commit that you want to remove
git branch temp <parent-commit>

# Rebase onto the parent-commit, starting from the commit-to-remove
git rebase --preserve-merges --onto temp <commit-to-remove> master

# Or use `-p` insteda of the longer `--preserve-merges`
git rebase -p --onto temp <commit-to-remove> master

# Verify your changes
git diff master@{1}

Lösung 4: Interaktive Rebases

Mit dieser Lösung können Sie die gleichen Aufgaben wie mit den Lösungen Nr. 2 und Nr. 3 ausführen, dh Commits weiter hinten im Verlauf ändern oder entfernen als mit Ihrem unmittelbar vorherigen Commit. Welche Lösung Sie verwenden, liegt also ganz bei Ihnen. Interaktive Rebases sind aus Leistungsgründen nicht gut geeignet, um Hunderte von Commits neu zu gründen. Daher würde ich in solchen Situationen nicht interaktive Rebases oder die Filterzweiglösung (siehe unten) verwenden.

Verwenden Sie Folgendes, um die interaktive Rebase zu starten:

git rebase --interactive <commit-to-amend-or-remove>~

# Or `-i` instead of the longer `--interactive`
git rebase -i <commit-to-amend-or-remove>~

Dies führt dazu, dass git den Festschreibungsverlauf auf das übergeordnete Element des Festschreibens zurückspult, das Sie ändern oder entfernen möchten. Anschließend wird eine Liste der zurückgespulten Commits in umgekehrter Reihenfolge in dem Editor angezeigt, für den git verwendet wird (dies ist standardmäßig Vim):

pick 00ddaac Add symlinks for executables
pick 03fa071 Set `push.default` to `simple`
pick 7668f34 Modify Bash config to use Homebrew recommended PATH
pick 475593a Add global .gitignore file for OS X
pick 1b7f496 Add alias for Dr Java to Bash config (OS X)

Das Commit, das Sie ändern oder entfernen möchten, befindet sich oben in dieser Liste. Um es zu entfernen, löschen Sie einfach die Zeile in der Liste. Andernfalls ersetzen „Pick“ auf „Bearbeiten“ auf der 1 st Linie, etwa so:

edit 00ddaac Add symlinks for executables
pick 03fa071 Set `push.default` to `simple`

Als nächstes geben Sie ein git rebase --continue. Wenn Sie das Commit vollständig entfernen möchten, ist dies alles, was Sie tun müssen (außer der Überprüfung, siehe letzter Schritt für diese Lösung). Wenn Sie andererseits das Commit ändern möchten, wendet git das Commit erneut an und pausiert dann die Rebase.

Stopped at 00ddaacab0a85d9989217dd9fe9e1b317ed069ac... Add symlinks
You can amend the commit now, with

        git commit --amend

Once you are satisfied with your changes, run

        git rebase --continue

Zu diesem Zeitpunkt können Sie die Datei entfernen, das Commit ändern und dann die Rebase fortsetzen:

git rm <file>
git commit --amend --no-edit
git rebase --continue

Das ist es. Als letzten Schritt sollten Sie unabhängig davon, ob Sie das Commit geändert oder vollständig entfernt haben, immer überprüfen, ob keine anderen unerwarteten Änderungen an Ihrem Zweig vorgenommen wurden, indem Sie den Status vor dem Rebase ändern:

git diff master@{1}

Lösung 5: Filtern von Zweigen

Schließlich ist diese Lösung am besten geeignet, wenn Sie alle Spuren der Existenz einer Datei vollständig aus dem Verlauf entfernen möchten und keine der anderen Lösungen der Aufgabe gerecht wird.

git filter-branch --index-filter \
'git rm --cached --ignore-unmatch <file>'

Dadurch werden <file>alle Commits entfernt, beginnend mit dem Root-Commit. Wenn Sie stattdessen nur den Festschreibungsbereich neu schreiben möchten, HEAD~5..HEADkönnen Sie dies als zusätzliches Argument an übergeben filter-branch, wie in dieser Antwort ausgeführt :

git filter-branch --index-filter \
'git rm --cached --ignore-unmatch <file>' HEAD~5..HEAD

Nach Abschluss des filter-branchVorgangs ist es normalerweise eine gute Idee, zu überprüfen, ob keine weiteren unerwarteten Änderungen vorliegen, indem Sie Ihren Zweig vor dem Filtervorgang vom vorherigen Status unterscheiden:

git diff master@{1}

Filter-Branch-Alternative: BFG Repo Cleaner

Ich habe gehört, dass das BFG Repo Cleaner- Tool schneller als ausgeführt git filter-branchwird. Vielleicht möchten Sie dies auch als Option überprüfen. Es wird sogar offiziell in der Filterzweigdokumentation als praktikable Alternative erwähnt:

Mit Git-Filter-Branch können Sie komplexe Git-Skript-Umschreibungen Ihres Git-Verlaufs vornehmen. Diese Flexibilität benötigen Sie jedoch wahrscheinlich nicht, wenn Sie einfach unerwünschte Daten wie große Dateien oder Kennwörter entfernen . Für diese Vorgänge sollten Sie The BFG Repo-Cleaner in Betracht ziehen , eine JVM-basierte Alternative zum Git-Filter-Zweig, die für diese Anwendungsfälle in der Regel mindestens 10-50-mal schneller ist und ganz andere Eigenschaften aufweist:

  • Jede bestimmte Version einer Datei wird genau einmal bereinigt . Die BFG bietet Ihnen im Gegensatz zum Git-Filter-Zweig nicht die Möglichkeit, eine Datei anders zu behandeln, je nachdem, wo oder wann sie in Ihrem Verlauf festgeschrieben wurde. Diese Einschränkung bietet den entscheidenden Leistungsvorteil von The BFG und eignet sich gut für die Bereinigung fehlerhafter Daten. Es ist Ihnen egal, wo sich die fehlerhaften Daten befinden, Sie möchten nur, dass sie nicht mehr vorhanden sind .

  • Standardmäßig nutzt die BFG Multi-Core-Maschinen voll aus und bereinigt parallel Commit-Dateibäume. GIT-Filterzweig cleans Festschreibungen sequentiell (dh in einer Single-Threaded - Weise), obwohl es ist möglich , Filter zu schreiben, die ihren eigenen Parallelismus umfassen, in den Skripten gegen jede ausgeführte begehen.

  • Die Befehlsoptionen sind viel restriktiver als der Git-Filter-Zweig und dienen ausschließlich der Aufgabe, unerwünschte Daten zu entfernen, z --strip-blobs-bigger-than 1M.

Zusätzliche Ressourcen

  1. Pro Git § 6.4 Git Tools - Umschreiben des Verlaufs .
  2. Git-Filter-Zweig (1) Handbuch Seite .
  3. git-commit (1) Handbuchseite .
  4. git-reset (1) Handbuchseite .
  5. git-rebase (1) Handbuchseite .
  6. Der BFG Repo Cleaner (siehe auch diese Antwort des Erstellers selbst ).
Gemeinschaft
quelle
Ist filter-branchUrsache Neuberechnung von Hashes? Wenn ein Team mit einem Repo arbeitet, in dem eine große Datei gefiltert werden soll, wie tun sie dies, damit alle den gleichen Status des Repos haben?
YakovL
@ YakovL. Alles berechnet Hashes neu. Tatsächlich sind Commits unveränderlich. Es erstellt einen völlig neuen Verlauf und bewegt Ihren Verzweigungszeiger darauf. Der einzige Weg, um sicherzustellen, dass jeder die gleiche Historie hat, ist ein Hard-Reset.
Mad Physicist
118

Wenn Sie seitdem nichts mehr festgeschrieben haben, nur git rmdie Datei und git commit --amend.

Wenn Sie haben

git filter-branch \
--index-filter 'git rm --cached --ignore-unmatch path/to/file/filename.orig' merge-point..HEAD

wird jede Änderung von merge-pointbis durchlaufen HEAD, filename.orig löschen und die Änderung neu schreiben. Verwenden --ignore-unmatchbedeutet, dass der Befehl nicht fehlschlägt, wenn aus irgendeinem Grund filename.orig in einer Änderung fehlt. Dies ist der empfohlene Weg aus dem Abschnitt "Beispiele" in der Manpage "git-filter-branch" .

Hinweis für Windows-Benutzer: Der Dateipfad muss Schrägstriche verwenden

Schwern
quelle
3
Vielen Dank! git filter-branch funktionierte für mich, wo das als Antwort angegebene Rebase-Beispiel nicht funktionierte: Die Schritte schienen zu funktionieren, aber dann schlug das Drücken fehl. Habe gezogen, dann erfolgreich geschoben, aber die Datei war noch da. Es wurde versucht, die Rebase-Schritte zu wiederholen, und dann wurde alles mit Zusammenführungskonflikten chaotisch. Ich habe jedoch einen etwas anderen Filter-Branch-Befehl verwendet, den hier angegebenen "An Improved Method": github.com/guides/completely-remove-a-file-from-all-revisions git filter-branch -f --index- Filter 'Git Update-Index - Dateiname entfernen' <Einführungsrevision-Sha1>
..HEAD
1
Ich bin mir nicht sicher, welche die verbesserte Methode ist. Git offizielle Dokumentation von git-filter-branchscheinen die erste zu geben.
Wernight
5
Schauen Sie sich zyxware.com/articles/4027/… an. Ich finde es die vollständigste und filter-branch
direkteste
2
@atomicules, wenn Sie versuchen, das lokale Repo auf das Remote-Repo zu verschieben, besteht git darauf, zuerst von der Remote zu ziehen, da es Änderungen enthält, die Sie lokal nicht haben. Sie können das --force-Flag verwenden, um es auf die Fernbedienung zu übertragen. Dadurch werden die Dateien vollständig von dort entfernt. Aber seien Sie vorsichtig, stellen Sie sicher, dass Sie nicht erzwingen, dass nur die Dateien überschrieben werden.
Sol0mka
1
Denken Sie daran , Windows zu verwenden "und nicht, 'da sonst ein nicht hilfreich formulierter Fehler "schlechte Revision" angezeigt wird.
cz
49

Dies ist der beste Weg:
http://github.com/guides/completely-remove-a-file-from-all-revisions

Stellen Sie einfach sicher, dass Sie zuerst die Kopien der Dateien sichern.

BEARBEITEN

Die Bearbeitung von Neon wurde bei der Überprüfung leider abgelehnt.
Siehe Neons Post unten, es könnte nützliche Informationen enthalten!


Zum Beispiel, um alle *.gzDateien zu entfernen , die versehentlich in das Git-Repository übernommen wurden:

$ du -sh .git ==> e.g. 100M
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch *.gz' HEAD
$ git push origin master --force
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --prune=now
$ git gc --aggressive --prune=now

Das hat bei mir immer noch nicht funktioniert? (Ich bin derzeit bei Git Version 1.7.6.1)

$ du -sh .git ==> e.g. 100M

Ich weiß nicht warum, da ich nur EINEN Hauptzweig hatte. Wie auch immer, ich habe mein Git-Repo endlich wirklich aufgeräumt, indem ich es in ein neues leeres und nacktes Git-Repository geschoben habe, z

$ git init --bare /path/to/newcleanrepo.git
$ git push /path/to/newcleanrepo.git master
$ du -sh /path/to/newcleanrepo.git ==> e.g. 5M 

(Ja!)

Dann klone ich das in ein neues Verzeichnis und verschiebe es über den .git-Ordner in dieses. z.B

$ mv .git ../large_dot_git
$ git clone /path/to/newcleanrepo.git ../tmpdir
$ mv ../tmpdir/.git .
$ du -sh .git ==> e.g. 5M 

(Ja! endlich aufgeräumt!)

Nachdem Sie überprüft haben, ob alles in Ordnung ist, können Sie die Verzeichnisse ../large_dot_gitund löschen ../tmpdir(möglicherweise in ein paar Wochen oder Monaten, nur für den Fall ...).

Darren
quelle
1
Das hat bei mir vor dem "Das hat bei mir immer noch nicht funktioniert?" Kommentar
Shadi
Gute Antwort, aber schlagen Sie vor, --prune-emptyden Befehl filter-branch hinzuzufügen .
ideasman42
27

Das Umschreiben des Git-Verlaufs erfordert das Ändern aller betroffenen Commit-IDs. Daher muss jeder, der an dem Projekt arbeitet, seine alten Kopien des Repos löschen und einen neuen Klon erstellen, nachdem Sie den Verlauf bereinigt haben. Je mehr Leute es stören, desto mehr brauchen Sie einen guten Grund dafür - Ihre überflüssige Datei verursacht kein wirkliches Problem, aber wenn Sie nur an dem Projekt arbeiten, können Sie den Git-Verlauf auch bereinigen, wenn Sie möchten zu!

Um es so einfach wie möglich zu machen, würde ich empfehlen, den BFG Repo-Cleaner zu verwenden , eine einfachere und schnellere Alternative zu dem git-filter-branchspeziell zum Entfernen von Dateien aus dem Git-Verlauf entwickelten. Eine Möglichkeit, die Ihnen das Leben hier erleichtert, besteht darin, dass standardmäßig alle Refs (alle Tags, Zweige usw.) verarbeitet werden, aber auch 10- bis 50-mal schneller.

Befolgen Sie die Schritte hier sorgfältig: http://rtyley.github.com/bfg-repo-cleaner/#usage - aber das Kernbit ist genau das: Laden Sie das BFG-JAR herunter (erfordert Java 6 oder höher) und führen Sie diesen Befehl aus ::

$ java -jar bfg.jar --delete-files filename.orig my-repo.git

Ihr gesamter Repository-Verlauf wird gescannt und alle benannten Dateien filename.orig(die nicht in Ihrem letzten Commit enthalten sind ) werden entfernt. Dies ist erheblich einfacher als git-filter-branchdas Gleiche zu tun!

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

Roberto Tyley
quelle
4
Dies ist ein hervorragendes Tool: Mit einem einzigen Befehl wird eine sehr übersichtliche Ausgabe erstellt und eine Protokolldatei bereitgestellt, die jedem alten Commit mit dem neuen übereinstimmt . Ich mag es nicht, Java zu installieren, aber das ist es wert.
Mikemaccana
Dies ist das einzige, was für mich funktioniert hat, aber das liegt daran, dass ich den Git-Filter-Zweig nicht richtig bearbeitet habe. :-)
Kevin LaBranche
14
You should probably clone your repository first.

Remove your file from all branches history:
git filter-branch --tree-filter 'rm -f filename.orig' -- --all

Remove your file just from the current branch:
git filter-branch --tree-filter 'rm -f filename.orig' -- --HEAD    

Lastly you should run to remove empty commits:
git filter-branch -f --prune-empty -- --all
paulalexandru
quelle
1
Während sich alle Antworten auf der Filterzweigspur zu befinden scheinen, zeigt diese, wie Sie ALLE Zweige in Ihrem Verlauf bereinigen können.
Cameron Lowell Palmer
4

Um das zu Charles Baileys Lösung hinzuzufügen, habe ich nur eine Git-Rebase -i verwendet, um unerwünschte Dateien aus einem früheren Commit zu entfernen, und es hat wie ein Zauber funktioniert. Die Schritte:

# Pick your commit with 'e'
$ git rebase -i

# Perform as many removes as necessary
$ git rm project/code/file.txt

# amend the commit
$ git commit --amend

# continue with rebase
$ git rebase --continue
Sverrir Sigmundarson
quelle
4

Der einfachste Weg, den ich gefunden habe, wurde von leontalbot(als Kommentar) vorgeschlagen, einem von Anoopjohn veröffentlichten Beitrag . Ich denke, es ist seinen eigenen Platz wert als Antwort:

(Ich habe es in ein Bash-Skript konvertiert)

#!/bin/bash
if [[ $1 == "" ]]; then
    echo "Usage: $0 FILE_OR_DIR [remote]";
    echo "FILE_OR_DIR: the file or directory you want to remove from history"
    echo "if 'remote' argument is set, it will also push to remote repository."
    exit;
fi
FOLDERNAME_OR_FILENAME=$1;

#The important part starts here: ------------------------

git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch $FOLDERNAME_OR_FILENAME" -- --all
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

if [[ $2 == "remote" ]]; then
    git push --all --force
fi
echo "Done."

Alle Credits gehen an Annopjohnund leontalbotfür den Hinweis.

HINWEIS

Beachten Sie, dass das Skript keine Validierungen enthält. Stellen Sie daher sicher, dass Sie keine Fehler machen und dass Sie ein Backup haben, falls etwas schief geht. Es hat bei mir funktioniert, aber in Ihrer Situation funktioniert es möglicherweise nicht. BENUTZEN SIE ES MIT VORSICHT (folgen Sie dem Link, wenn Sie wissen möchten, was los ist).

Lepe
quelle
3

Auf jeden Fall git filter-branchist der Weg zu gehen.

Leider reicht dies nicht aus, um es vollständig filename.origaus Ihrem Repo zu entfernen , da es weiterhin von Tags, Reflog-Einträgen, Fernbedienungen usw. referenziert werden kann.

Ich empfehle, auch alle diese Referenzen zu entfernen und dann den Garbage Collector aufzurufen. Sie können das git forget-blobSkript von dieser Website verwenden, um all dies in einem Schritt zu erledigen.

git forget-blob filename.orig

Nachoparker
quelle
1

Wenn es das letzte Commit ist, das Sie bereinigen möchten, habe ich es mit der Git-Version 2.14.3 (Apple Git-98) versucht:

touch empty
git init
git add empty
git commit -m init

# 92K   .git
du -hs .git

dd if=/dev/random of=./random bs=1m count=5
git add random
git commit -m mistake

# 5.1M  .git
du -hs .git

git reset --hard HEAD^
git reflog expire --expire=now --all
git gc --prune=now

# 92K   .git
du -hs .git
clarkttfu
quelle
git reflog expire --expire=now --all; git gc --prune=nowist eine sehr schlechte Sache. Wenn Ihnen nicht der Speicherplatz ausgeht, lassen Sie Git Garbage diese Commits nach einigen Wochen sammeln
avmohan
Vielen Dank für den Hinweis. Mein Repo wurde mit vielen großen Binärdateien eingereicht und das Repo wird jede Nacht vollständig gesichert. Also wollte ich einfach alles raus;)
clarkttfu
-1

Sie können auch verwenden:

git reset HEAD file/path

paolo granada lim
quelle
3
Wenn die Datei zu einem Commit hinzugefügt wurde, wird die Datei dadurch nicht einmal aus dem Index entfernt, sondern lediglich der Index auf die HEAD-Version der Datei zurückgesetzt.
CB Bailey