views:

120

answers:

3

Hello Git Geeks,

I now have a big honking, bloated, Git repository consuming mucho disk space on GitHub that I want to put on a diet. I need to discard ancient commits made early in the history of the project that are are essentially irrelevant to the current direction the project is going.

I am - and will always be - the sole user of this private repo.

Ideally I could do something like:

git rebase from-birth-of-repo-until-one-month-ago

Thanks,
Doug

A: 

Here's a recipe that will work in Git 1.7.2 or newer:

start=$starting_sha1
git checkout --orphan new_master $start
git commit -m 'new root'
git rebase --onto new_master $start master
git checkout master
git reset --hard new_master
git push -f origin master

Cleaning out the old objects that you no longer reference is more work, since they could be pointed to by reflogs, stash, tags, other branches, etc. Once you're sure these are fixed or removed, one or more of the following should help:

git prune
git gc
git repack -ad
cxreg
+1  A: 

The --squash option to git merge might be useful, and is available in git 1.4.1 and later. This stages the effects of a merge, but doesn't create a commit. So, if 143eff is the oldest commit you want to include in the squashed commit, your current branch is master and the "one month ago" commit is dcb7e5, you could do:

# Save the old position of "master" by creating a branch old-master:
$ git checkout master
$ git branch old-master

# Create and checkout a branch called "new-master" that's at the old commit:
$ git checkout -b new-master 143eff

# Stage the effects of merging the "one month ago" commit:
$ git merge --squash dcb7e5
Updating 143eff3..dcb7e5b
Fast-forward
Squash commit -- not updating HEAD
[... status output showing the staged changes ..]

# Create the squashed commit:
$ git commit -m "A commit squashing history up to a month ago"
# (You could use --amend if you want them to be squashed into 143eff
# instead of being a commit after that.)

Now you can check with git diff dcb7e5 new-master that they really are the same.

Next, you want to rebase the rest of your work onto new-master:

$ git rebase --onto new-master dcb7e5 master

That will leave you on a rebased master which should have the history you want. (Again, you can check this with git diff old-master master and git log. When pushing master to github you will need to add --force since you've rewritten history:

# Push master to github, with "--force", since you've rewritten history:
$ git push --force origin master

You can now remove new-master, which is at the squash commit, with:

git branch -d new-master

Apparently github runs git gc --auto on pushes, so you should see some space saving soon...

Mark Longair
A: 

Actually, I will go with boring old git rebase -i HEAD~Number where Number will walk me back from the head to the inital commit. More time consuming but at least I have a vague understanding of what it is doing. Thanks for all the suggestions.

dugla