8

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?

Akshunya
  • 153
  • 1
  • 2
  • 8

4 Answers4

10

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

Simba
  • 23,537
  • 7
  • 64
  • 76
  • bfg probably needs additional java installation also, which i want to avoid – Akshunya Sep 30 '19 at 09:22
  • @Akshunya I've tested my command on my side and it works. Are you on the commit 5 when you run the above command? – Simba Sep 30 '19 at 09:30
  • Yes i am on Commit 5. Do i need to follow an additional step here? – Akshunya Sep 30 '19 at 09:33
  • 1
    it doesn't work: the file is still visible in the history. beware of these solutions because they didn't properly work. The only way is to completely delete the whole repository and create a new one – Giox Apr 21 '21 at 12:19
  • 1
    this turned my whole repo into a mess, i should have read more about this command before running... Now every commit since the beginning of the repo is duplicated. – Stoyan Feb 10 '23 at 14:40
  • 1
    See /u/Monochrome's answer: one must run ``git push origin --force --all`` as well to force the same changes on the remote. – MRule Mar 15 '23 at 11:10
8

@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
Monochrome
  • 81
  • 1
  • 1
7

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.

nimrodm
  • 23,081
  • 7
  • 58
  • 59
  • In rebase command the commit hash should be of commit-4 instead of 3, right? – Akshunya Sep 30 '19 at 05:42
  • No. You rebase onto the commit preceding the one you want to edit. – nimrodm Sep 30 '19 at 05:50
  • Not working! After git reset credentials.json, i did git rebase --continue However file is till there. In fact when i did git commit -v it is not showing any changes at all – Akshunya Sep 30 '19 at 09:19
  • after the `git reset credentials.json` run a `git status` to verify that the credentials file is not in the 'untracked' list. – nimrodm Sep 30 '19 at 09:23
  • After saving the file (save buffer using Shift X and then Y for Yes), i did git reset. After that on doing git status, it is showing 1 command done, remaining commands and 'nothing to commit, working tree clean' – Akshunya Sep 30 '19 at 09:27
  • OK. Just tried this myself. After you select 'edit' and save the file. Use `git rm credentials.json` and `git commit --amend`. Then `git rebase --continue` – nimrodm Sep 30 '19 at 09:33
  • getting an error for could not apply 'Id for commit 5' as i guess this is where i am removing the credentials.json file which it is not consistent with my current changes. So should i do both edit commit 4 and edit commit 5 while saving the file in step 1? – Akshunya Sep 30 '19 at 09:40
  • Yes. But you don't need to explicitly edit commit-5. Git stops whenever it detects a conflict and you are immediately in edit mode. If commit-5 includes only the removal of the credentials file, just try `git rebase --continue`. Otherwise resolve the conflict and then continue. – nimrodm Sep 30 '19 at 09:48
  • 1
    Works perfectly fine! `git rebase --continue` works here. Also push to origin needs to be forced. So at the end `git push origin --force --all` does the job. – Akshunya Sep 30 '19 at 09:58
1

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)

Community
  • 1
  • 1
kapsiR
  • 2,720
  • 28
  • 36