Git Attic

Sometimes when using Git you find yourself with several branches that contain old code or code that has been shelved for the time being. You don't want to just throw it away, but it's really in the way in with your active branches.

I've usually used the solution of tagging and then deleting the branch. I call the tags something like "attic/experiment". This solves the problem of having uninteresting stale branches appear in the "git branch" output. However, "git tag -l" now shows my attic tags, and doing a "git push origin --tags" is no longer desirable, as I don't really want to push these stale branches to a public repository. Besides, if at all possible I like to keep my tags related to release versions, not unstable experiments or debug code.

The truth of the matter is that I need a separate place to store stale branches, neither in refs/heads nor refs/tags. To that end, I decided to use refs/attic. For starters, I moved refs/tags/attic to refs/attic. Bear in mind that tags are often cleaned away into the packed-refs file, so you may need to extract them from there if you're doing this. The advantage of moving the refs is that my stale branches are not visible in "git branch" nor "git tag -l". The downside is that it's difficult to list them at all! They appear in QGit, but I really wanted a way to manage my attic from the command line without using something as cumbersome as "git for-each-ref refs/attic".

To that end I created a simple bash script named "git-attic", which does everything I need. Place in your path and use as follows:

git attic
git attic store <ref> [<commit>]
git attic remove <ref>

Now, tidying away a stale branch named "experiment" is as simple as "git attic store experiment experiment" and then deleting the branch. If you don't specify a commit object to "git attic store", it will store the current HEAD. You can start using this straight away — it doesn't need any setting up.

The script is attached, but it's pasted below for your perusal. I hope this will be useful to someone else too :)

Edit: Thank you to Eric Raible from the Git mailing list, who suggested a couple of optimisations.

Edit: I've updated the script again since. See new post.

#!/bin/bash
###
# Original Author: Paul Gideon Dann
###

showUsage() {
  echo "Usage: git-attic"
  echo "       git-attic store  []"
  echo "       git-attic remove "
}

case $1 in
  "store")
    if [[ ! $2 ]]; then
      showUsage
      exit 1
    fi
    if [[ $3 ]]; then
      OBJECT_SHA1=`git-rev-parse --revs-only $3`
      if [[ ! $OBJECT_SHA1 ]]; then
        echo "$3 is not a recognisable commit object."
        exit 1
      fi
    else
      OBJECT_SHA1=`git show-ref --hash --head HEAD`
    fi
    git update-ref refs/attic/$2 $OBJECT_SHA1
    echo "$2 stored in attic."
    ;;

  "remove")
    if [[ ! $2 ]]; then
      showUsage
      exit 1
    fi
    OBJECT_SHA1=`git show-ref --hash attic/$2`
    if [[ ! $OBJECT_SHA1 ]]; then
      echo "$2 does not exist in the attic!"
      exit 1
    fi
    git update-ref -d refs/attic/$2 $OBJECT_SHA1
    echo "$2 removed from attic."
    ;;

  *)
    if [[ $1 ]]; then
      showUsage
    else
      # display contents of attic
      git for-each-ref --format="%(refname)" refs/attic | awk -F / '{print $3}'
    fi
    ;;
esac

Filename/TitleSize
Git Attic (git-attic.)1.1 KB

Back to top