Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

undo "git filter-branch ... -- --all"? in one command?

I started messing around with git filter-branch. The --all option rewrites all branches and tags. Cool. git filter-branch creates a backup of all refs it overwrites in refs/original. Very Cool. Now I'd like to blow all my experimenting with filter-branch away.

Is there an easy way to completely undo the effects of git filter-branch <whatever filter> -- --all? I.e. to restore all of the rewritten branches to their original state all at once?

If there isn't a preexisting way, there should be. If there isn't a preexisting way, does anybody have a short script that will do it?

Obviously there's workarounds. I could restore it manually, a branch at a time, as in this question. Or I could just nuke and re-clone. Either would get tedious quickly in a repo with many branches/tags that is (say) being split up into smaller repos.

like image 683
stochastic Avatar asked May 05 '14 22:05

stochastic


2 Answers

Here's a simple and safe way to undo a filter-branch:

git fetch . +refs/original/*:*

If the currently checked out branch (HEAD) is one of the branches to be restored, this command will fail. You can run git checkout --detach beforehand to let git fetch update all branches. Remember to checkout a branch after running git fetch!

Once the refs have been successfully restored, you can delete the refs/original refs safely with this command:

git for-each-ref refs/original --format='delete %(refname) %(objectname)' | git update-ref --stdin

Old answer:

git for-each-ref refs/heads refs/tags \
        --format='git update-ref "%(refname)" "%(refname)@{1 hour ago}"'

For added safety you could test whether the filter-branch actually did update the ref:

git for-each-ref refs/heads refs/tags --format='
        { git reflog -1 "%(refname)" | sed -n "/filter-branch: rewrite$/Q1"; } \
                  || git update-ref -m "reset to before filter-branch" \
                             %(refname) %(refname)@{1}' | sh -x
like image 70
jthill Avatar answered Sep 22 '22 17:09

jthill


Ehmm, move all refs from .git/refs/original to their place in .git/refs/heads? I mean literally move, these are plain text files. Also you may take a look into .git/packed-refs if it exists.

like image 28
user3159253 Avatar answered Sep 19 '22 17:09

user3159253