Note: after posting this, I heard back from Roberto Tyley, the creator of the BFG. I’d like to note that the BFG actually does its job really well. I was mostly really frustrated about how Git/GitHub doesn’t prevent a user from doing something that’s hard to undo. So my frustration is really about that, not really about the BFG. This post has been edited to reflect that.
Greg Wilson first said it, but I’ve come to agree. Git is an aggressively antisocial piece of software. Git is a piece of software that can make developers with any amount of experience feel dumb.
Recently, I accidentally checked a large file (greater than 100 Megs) into my local repo. When I tried to push to GitHub, of course, it refused it (I know about git large file storage, but I don’t have any).
So my local repo was screwed up. Of course, I did what seemed like the rational thing and deleted the file from my repo and recommitted. More than once. This is a mistake I’ve done more than once. So you need to scrub your git history with BFG so that GitHub will accept your lowly commits again.
The BFG documentation specifies how to fix a remote repo. I would say that this situation is much less common than the local situation. So I just decided to share how I got the BFG to work for the local repo situation.
I usually install the BFG through
brew install bfg. When you install it this way, you can just run BFG with
bfg. You can download it from the website, but you’ll have to call
java -jar bfg[VERSION].jar to run it.
Say you’ve accidently checked in a large file into your current repo. The first thing to do is to clone your local repo:
git clone --mirror local_repo
This will create another folder called
local_repo.git that you will do all the BFG magic on. This
local_rep.git is what is called a bare repo. I want to remove any files larger than 100 Megs, so I do this:
bfg -b 100M local_repo.git
If this doesn’t return an error, you can move on. However, I got the dreaded error:
Warning : no large blobs matching criteria found in packfiles - does the repo need to be packed?
Augh. Ok, some googling later I found that I needed to pack my orignal repo:
cd local_repo git repack
Okay, we need to get rid of our cloned repo and redo the last few steps.
rm -rf local_repo.git git clone --mirror local_repo bfg -b 100M local_repo.git
Then comes some git commands that no one has bothered to explain to me.
git reflog expire --expire=now --all && git gc --prune=now --aggressive git push
Uh oh, I get a
remote: error: refusing to update checked out branch: refs/heads/master error! More ugh.
Here’s the trick. Since you cloned a local repo, you need to set the origin of your current repo (
local_repo.git) to the GitHub remote. First we remove the current
origin, and then add back our remote.
git remote rm origin git remote add origin https://github.com/laderast/remote_repo
Finally, after much gnashing of the teeth, we can
Don’t forget to remove your now dirty
local_repo, and the mirrored copy, and then pull a fresh copy down!
##remove both original local repo and altered bare repo rm -rf local_repo rm -rf local_repo.git ##clone a fresh copy from GitHub git clone https://github.com/laderast/remote_repo
This may be obvious to the 10 people in the world who have read all of the git documentation, but I am not one of them. I’m stuck with git, unfortunately. I’m writing this post to remind me of what to do when I innocently do something like commit a large file to my repo.