12

I was wondering if anybody has a more efficient, more intelligent way to do this. The looping construct requires every deleted files to be expunged from every commit by reading each commit. With many commits, this takes a long time.

git log --pretty=format: --name-status | grep -i ^D | cut -f2- | sort -u | xargs -I {} git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch {}' HEAD

4 Answers4

5

That seems to remove each files one at a time.
Consider that git rm can take multiple files to be removed.

So one optimization would be to build that list and call the filter-branch once.
You can see one example of that approach in "Proper way to remove unwanted files with git filter-branch without git rm failing".

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
4

Just a small improvement to support recursive delete

git filter-branch --prune-empty --index-filter 'git log --pretty=format: --name-status | grep -i ^D | cut -f2- | sort -u | xargs git rm -r --cached --ignore-unmatch DoesNotExistInMyProject'
Omri
  • 887
  • 8
  • 24
2

For anyone else who might be looking for the same answer, I modified the original command above with the suggestions linked in the other thread and created this command which seemed to work for me.

git filter-branch --prune-empty --index-filter 'git log --pretty=format: --name-status | grep -i ^D | cut -f2- | sort -u | xargs git rm --cached --ignore-unmatch DoesNotExistInMyProject'
Db0
  • 151
  • 2
  • 10
1

Improved the command to avoid file names with a ' which causes xargs to bug

echo "/!\ This file contains a single quote ' and it's gonna bug with xargs, so it's excluded from the filter operation" ; bash -c "git log --pretty=format: --name-status | grep -i ^D " | grep \' git filter-branch -f --prune-empty --index-filter "git log --pretty=format: --name-status | grep -i ^D | grep -v \' | cut -f2- | sort -u | xargs git rm -r --cached --ignore-unmatch DoesNotExistInMyProject"

pedrotester
  • 179
  • 2
  • 11