Akshunya
Akshunya

Reputation: 433

Permanently removing a file from git history

Let's say i have done 5 commits in my git project.

At Commit 4 i accidentally added my credentials.json file and pushed to repo.
At Commit 5 i removed the file and did a commit and pushed this change to repo.

Currently the file is not showing in latest commit. But if a user checks commit history, he can go to commit 4 and check the contents of my file.

How can i permanently remove the file from commit history so that it looks like the file was never added to the repo.

Note:-
i have already tried below command:-

git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch Credentials.json" \
  --prune-empty --tag-name-filter cat -- --all

It does not throw any error but the file is not removed from History.

Actually the file is inside /src folder. But the strange thing is that when i give the below command (including the full path):-

git filter-branch --force --index-filter   "git rm --cached --ignore-unmatch ~full-path/src/Credentials.json"   --prune-empty --tag-name-filter cat -- --all

I get error as:- ~full-path/src/Credentials.json is outside repository.

Is it because i have already removed my file in commit 5? What can i do in this scenario?
Is creating a new repo from scratch the only option?

Upvotes: 15

Views: 23017

Answers (4)

Simba
Simba

Reputation: 27568

WARN: Always make a backup of the original repo before you start following operations.


No need to create a new repo. git filter-branch works.

Don't use full path in git filter-branch, use the relative path src/Credentials.json.

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch src/Credentials.json" --prune-empty --tag-name-filter cat -- --all

BTW, bfg is much easier to use for a newbie. (bfg accepts filename without path.)

bfg --delete-files Credentials.json

References

Upvotes: 17

Monochrome
Monochrome

Reputation: 91

@Simba's answer works, but you will also need to force-push afterwards with git push origin --force --all

So (1)

git filter-branch --force --index-filter "git rm -rf --cached --ignore-unmatch <relative_path_to_file>" --prune-empty --tag-name-filter cat -- --all

Then (2)

git push origin --force --all

Upvotes: 9

nimrodm
nimrodm

Reputation: 23779

Assuming no one had cloned the repository, you can use git rebase -i to rewrite the history and remove the file.

Use git rebase -i <commit-hash-of-commit-3>. This will open an editor with the list of commits starting at commit-4. You can choose to delete a commit (by deleting the line and saving the file), to edit it, etc.

Select 'edit' for commit-4. Save the file. You'll be back at the shell with the files added to the git 'index' but not yet committed.

Now you can git rm credentials.json to remove the file and git commit --amend to modify the commit. (updated)

Finally git rebase --continue to finish. You'll be back at the shell and the file will no longer be part of the repository.

If you had added a commit later on that depends on the Credentials.json file, you may get an error during the 'continue' phase. Git then stops at the problematic commit and you can again use git commands (reset/add) to modify the commit and continue.

Upvotes: 8

kapsiR
kapsiR

Reputation: 3177

I would recommend reading GitHubs help page:

In short:

  • You can use BFG Repo-Cleaner

    bfg --delete-files Credentials.json my-repo.git

  • You can use git filter-branch:

    git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all
    (where path is e.g. src/Credentials.json, This may help you too)

It's worth noting, that if anyone has already a copy of the repo, you have to delete it there too! (or you force re-clone/pull the repo)

Upvotes: 1

Related Questions