Skip to content

Instantly share code, notes, and snippets.

@brianloveswords
Last active January 24, 2024 12:28
Show Gist options
  • Star 61 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save brianloveswords/7545299 to your computer and use it in GitHub Desktop.
Save brianloveswords/7545299 to your computer and use it in GitHub Desktop.
git-obliterate: for removing sensitive files you may have committed from the entire history of the project.

git-obliterate

Has this ever happened to you?

cue video of someone accidentally committing super-secret-private-stuff.json

Time to blow away the entire project and start over right?

Wrong!

With git-obliterate, you can make it seem like the file has never existed in the project's history!

Usage

First, read this because I'm mostly just scripting a lot of what they say here: https://help.github.com/articles/remove-sensitive-data

Download the file, chmod +x it, and copy it to /usr/local/bin (or somewhere else in your PATH). Then you can do git obliterate <file> and it will wipe it from history. Singing Cher's “If I Could Turn Back Time” is optional. You will then have to git push --force to update your remote.

After that's done, you'll need to force update your remotes with git push --force, making sure to do all the branches and tags and everything that the file might have been in – if you're lucky, you will have caught it early and hopefully that should just be master.

Lazy Install

curl -O https://gist.github.com/brianloveswords/7545299/raw/6128cb79b624d915bfc1942177a3508fd47efbfe/git-obliterate && chmod +x git-obliterate && sudo mv git-obliterate /usr/local/bin
#!/bin/bash
file=$1
test -z $file && echo "file required." 1>&2 && exit 1
git filter-branch -f --index-filter "git rm -r --cached $file --ignore-unmatch" --prune-empty --tag-name-filter cat -- --all
git ignore $file
git add .gitignore
git commit -m "Add $file to .gitignore"
Copy link

ghost commented Feb 10, 2016

Thanks so much for writing this!

@DJTB
Copy link

DJTB commented May 24, 2016

Well played, sir.

@bew
Copy link

bew commented Aug 16, 2017

Hello, I have the following error:

git: 'ignore' is not a git command. See 'git --help'.
fatal: pathspec '.gitignore' did not match any files

Thanks

@GabLeRoux
Copy link

GabLeRoux commented Nov 19, 2017

@bew you were getting these errors for two reasons:

  1. You were missing the git ignore command. It comes from tj/git-extras. According to the above script, it is a requirement.
  2. The .gitignore file did not exist when it ran the git add .gitignore command. This will be fixed if git ignore command doesn't fail (it will create the .gitignore file).

✌️

@Babkock
Copy link

Babkock commented Dec 12, 2018

Didn't work. Again. Thanks for being yet another thing that didn't work for me.

EDIT: Came back to say I actually had to blow away the project and start over. Your cute script was of 0 help to me.

@Bachsau
Copy link

Bachsau commented Mar 24, 2019

And interactive rebase on OFFENDING~1 would have done.

@gojimmypi
Copy link

gojimmypi commented Apr 28, 2019

@Babkock I thought I saw a similar result, but after a local git pull / git push indeed my offending file was obliterated.

  • edit: note that if the offending file was committed with another file at some previous point, the history of the offending file will still be available with the history of that other file.

@codeallthethingz
Copy link

codeallthethingz commented Dec 10, 2021

If you're coming to this thread to obliterate, the 2021 option is to use this tool - https://rtyley.github.io/bfg-repo-cleaner/

It's fantastic. Way faster than obliterate and useful options to delete files bigger than Xmb

@davemc0
Copy link

davemc0 commented Mar 25, 2022

The 2022 way to obliterate a file is to just type the following line. No need to download any scripts or tools at all. It's line 4 of the above git-obliterate script:
git filter-branch -f --index-filter "git rm -r --cached $file --ignore-unmatch" --prune-empty --tag-name-filter cat -- --all
Just replace $file with your filename.

After this finishes, don't forget to push your changes to the remote using:
git push --force

Since this isn't in the script I think not doing this is why some people say the script doesn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment