I accidentally delete a file from my repo using git filter-branch:
git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch images/thumb/a.JPG' HEAD
How can I undo this? Is it possible? i.e. is the file permanently deleted?
DESCRIPTION. Lets you rewrite Git revision history by rewriting the branches mentioned in the <rev-list options>, applying custom filters on each revision. Those filters can modify each tree (e.g. removing a file or running a perl rewrite on all files) or information about each commit.
The basic syntax is git filter-branch <filters> branch_name . You can use HEAD or @ to refer to the current branch instead of explicitly typing branch_name . A very simple and useful filter is the subdirectory filter. It makes a given subdirectory the repository root.
This can be installed in the directory pointed to by git --html-path . Note that git filter-repo -h will show a more limited built-in set of instructions regardless of whether the html version of help is installed.
Git reset should generally be considered a 'local' undo method. A reset should be used when undoing changes to a private branch. This safely isolates the removal of commits from other branches that may be in use by other developers. Problems arise when a reset is executed on a shared branch and that branch is then pushed remotely with git push.
How to undo a commit with git checkout. Using the git checkout command we can checkout the previous commit, a1e8fb5, putting the repository in a state before the crazy commit happened. Checking out a specific commit will put the repo in a "detached HEAD" state. This means you are no longer working on any branch.
git filter-branch refuses to start with an existing temporary directory or when there are already refs starting with refs/original/, unless forced. This option will cause the mapping from old to new objects to be loaded from named branch upon startup and saved as a new commit to that branch upon exit, enabling incremental of large trees.
Undo with: git revert <SHA> What’s happening: git revert will create a new commit that’s the opposite (or inverse) of the given SHA. If the old commit is “matter”, the new commit is “anti-matter”—anything removed in the old commit will be added in the new commit and anything added in the old commit will be removed in the new commit.
When you use git filter-branch
, a backup file is created in
refs/original/refs/heads/master
If you used the command in branch master
. You can check if you have the backup in .git/refs
directory. With this in mind, you can use this backup to recover your files with:
git reset --hard refs/original/refs/heads/master
Probably a more proper way than just doing hard reset to the original master would be to restore all refs rewritten by git filter-branch
, and maybe even delete backup refs afterwards in order to be able to invoke git filter-branch
again without --force
:
for orig_ref in $(git for-each-ref --format="%(refname)" refs/original/); do git update-ref "${orig_ref#refs/original/}" $orig_ref git update-ref -d $orig_ref # to also remove backup refs done
And after that:
git reset --hard master
Here's (arguably) a bit more git'ish way to perform the same without a shell for-loop:
git for-each-ref --format="update %(refname:lstrip=2) %(objectname)" refs/original/ | git update-ref --stdin git for-each-ref --format="delete %(refname) %(objectname)" refs/original/ | git update-ref --stdin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With