Delete commits before date

One thing that has come up at work is the size and speed of our git repository. It is over 4GB with more than 15,700 commits and just under 46,000 files. This makes things very slow. It has also made cloning the repository physically impossible as the server runs out of memory about 60% of the way through (I tried continuously between 22:00 and 1:00 last night/this morning). As such, it has been decided that this needs to be corrected.

One thing was that we used to keep many SVGs and Adobe Illustrator files in our history. We could remove these and free up half the repository, but do we need all our history since the beginning of this repo? The answer was no. We do not need anything older than three months. We plan to split the repo apart to give each team a different repo. Having separate repositories avoids merges similar to those that have destroyed work in the past.

The question is how to get rid of these commits? There are many resources for doing this, including a great Stack Overflow post and a convenient tip on Code Project, and in the Git docs themselves. At first, I sought to remove the offending images folder from the history separately from the date-based removal, but this was not necessary because three months ago, this was already removed from the repository. As such, I merely needed to delete everything more than three months old. Things were a bit tricky, though, because of how git filter-branch behaved regarding variables in the shell. Ultimately I ended up with the solution below for cleaning out the history. The script is not the whole solution. After running it, it is necessary to repack and forcibly push it to the server. The push is a destructive operation, so everyone with a copy will likely need to download the repository again, or you risk the old stuff coming back. The code below is for a Mac, so particular parameters may need to change.

  git filter-branch --commit-filter '\
  commitDate=$(echo "$GIT_COMMITTER_DATE" | cut -d " " -f 1 | cut -d "@" -f 2);\
  oldDate=$(date -v-3m -v0H -v0M -v0S "+%s");\
  if [ $commitDate -lt $oldDate ];\
  then\
    skip_commit "$@";\
  else\
    git commit-tree "$@";\
  fi' -- --all
Show Comments