2016-04-27 9 views
0

Ich versuche, git filter-branch zu verwenden und meinen initialen Commit bestehend aus einem .gitignore (rebased in den Zweig danach) in Kraft treten zu lassen. Diesegit filter-branch, das meine anfänglichen commits respektiert .gitignore

ist, was ich laufen:

git filter-branch -f --tree-filter 'git rm -r --cached . && git add .' --prune-empty 

Dieser Befehl jedoch verlässt das Repository unverändert.

Warum?

Ich frage mich auch, warum der folgende Befehl nicht alle Dateien im Repository entfernen:

git filter-branch -f --tree-filter 'git rm -r --cached .' 

Antwort

2

A --tree-filter arbeitet nicht an/mit dem Index. Stattdessen kopiert es jedes Commit in ein temporäres Verzeichnis, das als Arbeitsbaum verwendet wird, führt den Befehl in diesem temporären Verzeichnis aus und macht das neue Commit aus den verbleibenden und/oder neuen Dateien im temporären Verzeichnis. Änderungen, die Sie während dieses Vorgangs am Index selbst vornehmen, werden effektiv ignoriert.

Das bedeutet, dass Sie aus dem Arbeitsbaum genau die Dateien entfernen müssen, die Ihr neues .gitignore verhindert, hinzugefügt zu werden. Sie könnten dies manuell mit git rm --cached in einem --index-filter tun, die viel schneller wäre, aber wenn Sie git die Arbeit für Sie in einem --tree-filter tun wollen, können Sie den gleichen Trick git selbst verwenden (siehe Fußnote): verwenden git clean (mit -x), um das temporäre Verzeichnis zu bereinigen.


Das ist nicht ganz richtig: filter-branch ‚s --tree-filter Code git read-tree verwendet den Index vor (Wieder-) bevölkern das temporäre Verzeichnis (die wiederum zu bevölkern, bedeutet es einige Arbeit zu tun hat zu reinigen, die temporäres Verzeichnis von früheren Commits, für die es git clean verwendet). Dann, nach eval Ihren Filter, verwendet es den Index erneut, um zu überprüfen, was im temporären Verzeichnis getan wurde. Wenn Sie git rm -r --cached . und dann git add . vergleichen, vergleicht es den resultierenden Index, der nicht mehr Ihre ignorierten Dateien enthält, mit dem Arbeitsbaum und ... fügt Ihre ignorierten Dateien hinzu. Argh!

0

Diese Lösung funktioniert, außer es keine Leerzeichen in Dateinamen unterstützt leider:

git filter-branch -f --tree-filter 'ls -r | xargs --no-run-if-empty \ 
git check-ignore --no-index | xargs --no-run-if-empty rm' --prune-empty 

Es produziert auch extrem lange Leitungen zu git check-ignore, nämlich eine Liste aller Dateien im Arbeitsverzeichnis (rekursiv). Kann git check-ignore Rekursivität nicht selbst behandeln? Und Leerzeichen in Dateinamen, wie unterstützt man diese?