One weird thing about git is that, even though you may have deleted a bunch of branches, it will still hang onto their contents for a long time. This is good when you accidentally delete a branch you care about. Just find it in the reflog and you're back in business.

But what about about when you're sure you want something gone? Say, you accidentally checked in a video file rather than a symlink and now your repo is 17GB? Or there's an embarrassing secret branch in your repo that needs to disappear before the congressional oversight committee knocks on your door in 20 minutes? Let's kill that data for good.

       git branch -d white-house-email
       git reflog expire --expire=0 --expire-unreachable=0 --all
       git gc --prune
       git repack -a -d

That deletes the secret branch, then expires all the reflogs so all refs that could be pointing to it are deleted. Finally, we prune all unreachable objects, repack the repo, and we're done. All traces of the branch are gone and the disk space has been recovered.

Remember to delete all branches that could lead to the bad data. That includes remotes. Use git branch -a -v to see if there's anything you forgot about.

Pushing

Let's say that you have two branches in your repo, charity-donations and shady-deals. You want to put charity-donations up to a public server, but you don't want any of the information in shady-deals to go up. Can you safely git push charity-donations?

TODO: I *think* that if you push after committing, all objects are separate, and only the objects needed by the charity-donations branch will be sent to the remote (so long as you're using a smart transport like git or ssh, not brain-dead like rsyncing). However, if you repack everything into one big packed blob, git will just push the whole blob up. Shady deals and everything. JUST A GUESS!