How to permanently remove a sensitive file in Git from history

If you have committed a sensitive file in Git by mistake, for example a file containing a password, you can choose to remove this file from Git (and rewrite history).

NOTE: only do this if you know what you’re doing. Rewriting history in Git is usually considered a bad-practice, especially if you are collaborating with other people. If the file with the sensitive data has already been pushed to a remote (e.g. GitHub), then make sure you change the password everywhere you used it, since you must assume the password has already been compromised!

1. Always create a copy of your existing repository on the filesystem

To always be on the safe side, make sure to make a temporary back-up folder of your Git repository on your local machine. When rewriting history you are permanently deleting files, so make sure you have a back-up in case things go wrong.

2. Execute “git filter-branch” command.

Go to your Git repository, open up a command line, and then issue the following command. Replace [.path/to/file.extension] with the path to the file you want to delete. Note: this command will remove the entire file from your repository! If you need to re-add this file (with sensitive data removed), make sure to create a copy of it somewhere else before running this command.

git filter-branch -f --prune-empty --index-filter "git rm -r --cached --ignore-unmatch ./path/to/file.extension" HEAD

If things go well, you should get the following output:

WARNING: git-filter-branch has a glut of gotchas generating mangled history
         rewrites.  Hit Ctrl-C before proceeding to abort, then use an
         alternative filtering tool such as 'git filter-repo'
         (https://github.com/newren/git-filter-repo/) instead.  See the
         filter-branch manual page for more details; to squelch this warning,
         set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite f62e4102c1965717c0120d95779c156cdd061220 (3/9) (1 seconds passed, remaining 2 predicted)    rm 'path/to/file.extension'
Rewrite a04aa37d4c195e9cc3b864d36d2628636a3e293e (7/9) (2 seconds passed, remaining 0 predicted)    rm 'path/to/file.extension'
Rewrite 6f41a8f5b8b1295378e3a371163af84da321dd5c (7/9) (2 seconds passed, remaining 0 predicted)    rm 'path/to/file.extension'
Rewrite d4db66a4eba41f8b48e1386f6f9d4a4d868f7c10 (7/9) (2 seconds passed, remaining 0 predicted)    rm 'path/to/file.extension'

The commits you see above are now rewritten, with the file deleted. You can now re-add and commit the backup of the file (with the sensitive data removed).

3. Made a mistake while issuing the git filter-branch command?

If you made a mistake while executing the command in step #2 and deleted too many files, and you forgot to make a back-up (as instructed in step #1), then you might be able to still return to the previous situation with the following command.

Note: mileage may vary with this command, as Git only keeps a backup of the original situation (before git filter-branch) for a limited period of time, and only on your local machine where you executed this statement.

3.1 Restore Git repository as it was BEFORE the git-filter branch

git reset --hard refs/original/refs/heads/master

3.2 Permanently delete refs/original/*

If you want to delete this auto-backup that Git creates, to make sure that all sensitive data is really gone, even on your local machine, you can use this command. Please note: only execute this command if your repository is in a good working order, there is no way to retrieve any deleted files after this!

git update-ref -d refs/original/refs/heads/master
Published
Categorized as Git

By Leendert de Borst

Freelance software architect with 10+ years of experience. Expert in translating complex problems into creative & simple technical solutions.

Leave a comment

Your email address will not be published.