Question: I am trying to use git filter-branch and to let my intial commit consisting of a .gitignore (rebased into the branch afterwards) come into effect.

This is what I run:

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

```

This command however leaves the repository unchanged.

Why?

I also wonder why the following command does not remove all files in the repository:

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

```

Answer: 
A `--tree-filter` does not operate on/with the index.1 Instead, it copies each commit to a temporary directory used as a work-tree, runs your command in that temporary directory, and makes the new commit out of whatever files remain and/or are new in the temporary directory. Changes you make to the index itself during this process are effectively ignored.

What this means is that you must remove from the work-tree exactly those files your new `.gitignore` prevented from being added. You could do this manually with `git rm --cached` in an `--index-filter`, which would be much faster, but if you want to get git to do the work for you in a `--tree-filter`, you can use the same trick git itself uses (see the footnote): use `git clean` (with `-x`) to clean up the temporary directory.

---

1This is not quite true: `filter-branch`'s `--tree-filter` code uses `git read-tree` to populate the index before (re)populating the temporary directory (which in turn means it has to do some work to clean out the temporary directory from previous commits, for which it uses `git clean`). Then, after `eval`ing your filter, it uses the index again to inspect what was done in the temporary directory. When you `git rm -r --cached .` and then `git add .`, it compares the resulting index, which no longer has your ignored files, to the work-tree and ... *adds your ignored files*. Argh!
This solution works, except it does not support spaces in filenames:

```
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

```

It also produces extremely long lines to `git check-ignore`, namely a list of all files in the working directory (recursive). Can´t `git check-ignore` handle recursivity by itself? And spaces in filenames, how to support those?