Remove a directory permanently from git

In my personal git repo, I have a directory that contains thousands of small images that are no longer needed. Is there a way to delete them from the entire git history? I have tried

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch imgs" HEAD


  • Restore files removed by Git checkout
  • Can't get git to stop outputting to StdErr
  • Git and WordPress (+ managing plugins and media)
  • How to avoid Visual Studio rebuild after switching Git branches back and forth?
  • Set up a default directory structure on git init
  • Run resharper inspections on git pull request changes only
  • git filter-branch --tree-filter 'rm -fr imgs' HEAD

    but the size of the git repo remains unchanged. Any ideas?


  • Git & Deployment: Local changes staged, committed, and pushed, not showing on remote
  • how to search for all commits of a particular filename?
  • Git log outputs in a specific revision range
  • Rebasing a branch that has been branched from
  • Git pre-push hook, enumerating all un-pushed commits
  • Where is git-blame in SourceTree
  • 6 Solutions collect form web for “Remove a directory permanently from git”

    Actually none of these techniques workedfor me.
    I found the most reliable was was to simply pull locally into another repo:

    git pull file://$(pwd)/myGitRepo

    It also saves you the hassle of deletig old tags.

    see the story on my blog:

    The ProGit book has an interesting section on Removing Object.

    It does end with this:

    Your history no longer contains a reference to that file.
    However, your reflog and a new set of refs that Git added when you did the filter-branch under .git/refs/original still do, so you have to remove them and then repack the database. You need to get rid of anything that has a pointer to those old commits before you repack:

    $ rm -Rf .git/refs/original
    $ rm -Rf .git/logs/
    $ git gc
    $ git prune --expire 

    (git prune --expire is not mandatory but can remove the directory content from the loose objects)
    Backup everything before doing those commands, just in case 😉

    git-filter-branch by default saves old refs in refs/original/* namespace.

    You need to delete them, and then do git gc --prune=now

    Brandon Thomson asked in a comment to Rainer Blome‘s solution if this just fixed the gitk view or if the refs will be really gone. A good way to check this is to remember one of the sha1 hashes (or a unique prefix of it) of the old commits and try

    $ git ls-tree hash-value

    This should show you the content of the repos main folder as it was in this commit. After

    $ rm -Rf .git/refs/original
    $ rm -Rf .git/logs/

    as shown by VonC and removing the refs/original/… lines from .git/info/refs and .git/packed-refs as shown by Rainer Blome, a final

    $ git gc --prune=now

    made not only the refs, but also the old objects (commits, trees, and blobs) go away. The above shown git ls-tree hash-value proves this.
    Another nice command to check this is git count-objects -v (run it before the filter-brach and after the pruning and compare the size).

    Note: As I’m not allowed yet to comment on the other answers, I had to write a new one although it mainly combines previous given answers.

    If you want to go the manual cleanup route, there are some more files that may also contain
    a ref to the position of your original branch before the git-filter-branch.
    For example, I filtered my “home” branch:


    179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home


    179ad3e725816234a7182476825862e28752746d refs/original/refs/heads/home

    After I removed those lines, gitk did not show the old commits any more.

    As this is an old question, perhaps some of this wasn’t possible back then. This also assumes you’re using bash or cygwin.

    Warning: The second and third lines will permanently delete all commits unreachable from your branches/tags.

    After running filter-branch, do

    for ref in $(git for-each-ref --format='%(refname)' refs/original); do git update-ref -d $ref; done
    git reflog expire --expire=now --all
    git gc --prune=now

    git for-each-ref --format='%(refname)' gets the reference names, and git update-ref -d deletes the reference. It is generally better not to modify the .git folder directly, and in particular this command handles the case when the refs are in packed-refs.

    The second and third lines are taken directly from How to clean up unused side-branches in your commit trees?.

    Git Baby is a git and github fan, let's start git clone.