That moment when you forget to add your env files into .gitignore...
Just the other day, I was wrapping up a remote pair-programming session with a colleague and I had to check the code in to GitHub.
By habit, I did the following:
$ git add .
$ git commit -m 'Inital Commit'
$ git push origin HEAD
Then went about my day before my colleague picked up on the mistake I made - I had checked in a .env
file unwittingly.
A .env
file is what developers typically use to store variables, in this case sensitive data like API keys or Passwords, when developing locally to pass into an application environment. Typically, you have an accompanying .gitignore
file that contains a list of files or folders that Git will explicitly ignore. However, we didn't have one in this project.
I panicked at the thought of how a security audit would have auditors breathing down my neck if we had let this slip.
With Git, you cannot just remove or replace the file as it would be still available in your Git history, you need to also purge it from your repository history to ensure that it is unreachable. If you have worked with Git long enough, you understand how tricky it is to rewrite history, especially when files have been committed and pushed on a remote branch.
Thanks to Google and Github's documentation, I discovered that I could completely remove a file from a repository - using git filter-branch
.
git filter-branch
git filter-branch
is a feature to help with rewriting branches.
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <PATH_TO_FILE_TO_DELETE>" --prune-empty --tag-name-filter cat -- --all
Breaking down the command, we get:
—- force
To force git filter-branch to start without having an existing temporary directory
—— index-filter
One of the filters we can use. This is for rewriting index, and commonly used with the next command.
"git rm —cached —ignore-unmatch <PATH_TO_FILE_TO_DELETE>"
Completely remove any history of the file.—ignore-unmatch
here basically ignores when the file is entered into Git history.
—-prune-empty
Since we are removing a file, there might be commits that were made that introduces this file to the repository. After removing this file, the commit will be empty. This command removes any empty commits.
-tag-name-filter cat -- --all
Filters all the references and rewrites all branches and tags.
Making your problems go away, one git command at a time
GitHub's documentation also recommends using BFG Repo-cleaner, a faster, simpler alternative to git filter-branch for removing unwanted files, but I have yet to try it.
With the offending file removed, I proceeded to add the .gitignore
file and .env.sample
, before pushing back to the repository.