2014-09-29 5 views
11

Vor vielen Monden habe ich einen Teilbaum zu meinem git Repository hinzugefügt. Dieser Teilbaum enthielt mehrere Ordner und Dateien. Ich habe den Unterbaum hinzugefügt, anstatt ein Submodul zu erstellen (wie empfohlen). Jetzt merke ich, dass ich nur eine der Dateien in der Teilstruktur und keine der restlichen Dateien möchte. Noch schlimmer, wenn andere clone mein Repository, was sie bekommen, ist nicht das, was erwartet wird - es gibt einige Konflikte mit dem Teilbaum und dem anderen Code, den ich erstellt habe.So entfernen Sie zuvor hinzugefügt git Unterbaum und seine Geschichte

I ride der Dateien/Ordner mit

, ich bin aber
git rm subtree–folder1 subtree_folder2 subtree_files.* 

bekommen kann immer noch mit einer langen Geschichte von der Unterstruktur begeht links.

Ich habe eine ganze Menge Entwicklung gemacht, seit ich den Teilbaum ursprünglich hinzugefügt habe und den Commit-Verlauf, den ich generiert habe, nicht verlieren kann.

kurz In diesem ist das, was ich möchte:

  1. Entfernen Sie alle Unterbaum Dateien/Ordner.
  2. Vergessen Sie die Geschichte aller Teilbaum-Commits.
  3. Links mit nur meinem Code und meiner Geschichte.

Ist das möglich?

PS. Eine mögliche Komplikation ist, dass ich die einzelne Header-Datei, die ich behalten wollte, aus dem Teilbaum in einen Ordner in meinem Code verschoben habe. Ich hoffe, das ist nicht, was mich davon abhält, die Geschichte der Teilbäume zu vergessen.

Ein Versuch

Nach einer frischen Kasse von dem Remote-Server habe ich die folgenden:

$ ls 
.git    CMakeLists.txt Read.cpp   logging.conf 
.gitignore  ENDF6   TestData   src 
.sparse-checkout LICENCE   doc    test 
.travis.yml  README.md  include   tools 

Wo .gitignore nur hat: build/ debug/

Wenn ich versuche, den Befehl wie vorgeschlagen, bekomme ich keine sehr glückliche Antwort:

$ git filter-branch --index-filter 'git rm --cached -rf test tools src doc LICENCE README.md .travis.yml' HEAD 
Rewrite 2fec85e41e40ae18efd1b130f55b14166a422c7f (1/1701)fatal: pathspec 'test' did not match any files 
index filter failed: git rm --cached -rf test tools src doc LICENCE README.md .travis.yml 

Ich bin mir nicht sicher, warum es sagt, es hat ein Problem mit test, wenn es eindeutig da ist. Ich bin verwirrt.

+0

Haben Sie versucht, einfach 'git rm ' zu verwenden, um den Teilbaum zu entfernen? –

+0

@hunch_hunch Ich habe das genauso gemacht wie die Befehle hier: http://stackoverflow.com/questions/15890047/how-to-remove-history-of-deleted-git-subtree-folder, aber ich habe immer noch die ganze Geschichte von der Teilbaum. Hilfe! – jlconlin

+0

Sie können Ihren Repository-Verlauf über Rebase oder Filter-Branch neu schreiben? –

Antwort

15

Sie müssen Verwenden Sie einen Filterzweig zusammen mit der Option --prune-empty, um alle Commits zu entfernen, die keine neuen Änderungen mehr bewirken.

git filter-branch --index-filter 'git rm --cached --ignore-unmatch -rf dir1 dir2 dirN file1 file2 fileN' --prune-empty -f HEAD 

Danach, wenn Sie Speicherplatz wiederherstellen möchten, müssen Sie alle ursprünglichen Refs löschen, dass Filterzweig gespeichert, verfallen die reflog und Müll sammeln.

+0

Danke für Ihre Hilfe! Es ist hier nicht gezeigt, aber in unserem Chat @AndrewC zur Verfügung gestellt die erforderliche Antwort. – jlconlin

+0

git log zeigt immer noch die Geschichte. Vielleicht vermisse ich etwas ... –

+0

@SkylarSaveland Siehe die [Chat] (http://chat.stackoverflow.com/rooms/62556/discussion-between-jeremy-and-andrew-c) jlconlin bezieht sich darauf, obwohl es sollte hier die Lösung sein. Mm – Llopis

2

Sie können git filter-branch verwenden, um eine Operation auf alle Commits anzuwenden, die Sie in einer Verzweigung vorgenommen haben. Dies beinhaltet das Löschen von Dateien aus jedem Commit, während Sie den gesamten Verlauf neu schreiben. Eine gute Beschreibung und Anleitung finden Sie hier: http://gitready.com/beginner/2009/03/06/ignoring-doesnt-remove-a-file.html. Sie können die folgende Frage auch nützlich finden: Completely remove files from Git repo and remote on GitHub (dort finde ich den Link). Der eigentliche Befehl, den Sie mit dieser Lösung ausführen, wird etwa git filter-branch --index-filter 'git rm --cached -rf subtree–folder1 subtree_folder2' HEAD sein.

Ein anderer Weg, der wahrscheinlich zu viel ist für das, was Sie tun, ist Rosinenpicken. Cherry-Picking ermöglicht es Ihnen, jeden Abschnitt Ihrer Geschichte, den Sie mögen, mit jedem Detailgrad, den Sie mögen, neu zu schreiben: http://git-scm.com/docs/git-cherry-pick. Sie werden so etwas wie git reset --hard <HASH of commit that introduced the subtree>, gefolgt von einer Reihe von

git cherry-pick -n <following commit hashes> 
git reset 
git add -p 
git commit 

für jede nachfolgende tun wollen verpflichten Sie gemacht hatte.Dadurch können Sie den Teilbaum von jedem Commit, das Sie in der Vergangenheit gemacht haben, entfernen. Weitere Informationen zum effektiven Rosinenpflücken finden Sie unter partly cherry-picking a commit with git. Wenn Sie mit dieser Version der Löschung fertig sind, werden Sie die alten Commits zu entfernen, die nicht mehr Teil Ihrer Branche sind:

git reflog expire --expire-unreachable=now --all 
git gc --prune=now 

Andere verwiesen Fragen: How to move a branch backwards in git? Listing and deleting Git commits that are under no branch (dangling?)

Verwandte Themen