Easily migrate git repositories to Bitbucket

February 27, 2014

We recently migrated our team's repositories (103 of them) to Bitbucket. For the past few years we had been hosting them on a Gitolite (v1) instance that we had set up at git.designhammer.net and were maintaining on a Rackspace slice. This setup served us very well but moving to Bitbucket was an easy choice, given that we didn't want to spend our time maintaining the Gitolite instance, and the cost of Bitbucket would be about the same.

After we decided to make the switch, migrating to Bitbucket was really easy. Here's a quick guide to how we went about the process as well as some gotchas to look out for.

Bitbucket setup

First we created a DesignHammer team in Bitbucket, invited our colleagues, and then added them to the team. Bitbucket offers the same granularity that Gitolite supports in assigning permissions and roles on a per-repository basis, as well as defining roles for different people on your team, but of course the administration is a lot simpler since its through the Bitbucket UI, instead of Gitolite's configuration file.

As part of this process, make sure your colleagues upload their SSH keys to their Bitbucket account so they are not locked out of pushing/pulling to repos.

Migrating repos

Next, we grabbed a list of all our existing repositories. With Gitolite, you can run the command ssh git@git.designhammer.net info and get back a list of all the repositories you have access to. (Of course, make sure you do this as a user who has access to all the repos so you don't leave anything behind.) The output you get back is something like:

R   W   some-repo
R   W   another-repo

I'm sure there is a better way to do this, but the quickest way for me was to fire up Sublime Text and use the multiple carets feature to select every line, then deleting the "R W " from the beginning of each line, so the result was:


Ok, now it's time to point our migration script at the repos.txt file and push them up to Bitbucket. One thing to note: run this script in a temporary directory from a server you control, not from your laptop; the network speeds will be much better if this is run in the cloud.

# Usage: ./bitbucket-migrate.sh repos.txt
# repos.txt should have one repository per line.
echo "Reading $1"
while read line
        echo "###"
        echo "Processing $repo"
        git clone --bare git@git.designhammer.net:$repo
        cd $repo.git
        echo "Creating repo in Bitbucket"
        curl --user USER:PASSWORD https://api.bitbucket.org/1.0/repositories/ --data name=$repo --data is_private=true --data owner=designhammer
        echo "Pushing mirror to bitbucket"
        git push --mirror git@bitbucket.org:designhammer/$repo.git
        cd ..
        echo "Removing $repo.git"
        rm -rf "$repo.git"
        echo "Waiting 5 seconds"
        echo "###"
        sleep 5;
done < $1

As you can see this is a very simple script built around git clone --bare and git push --mirror. These commands are important as they ensure that all tags and branches are migrated over to Bitbucket. You can also see in the API call to Bitbucket that we're setting the owner to designhammer and that the visibility of the repos should be private. Finally, the local copy of the repo is removed so we don't fill up the server with repos it doesn't need.

Wrapping up

After that all of our repos were mirrored over at Bitbucket, we used Bitbucket's custom domain feature to add a CNAME for git.designhammer.net to map to bitbucket.org. Since this takes about 20 minutes to take effect, it was a good time for our developers to do the three manual steps in the process:

  1. Each developer had to remove the entry in their ~/.ssh/known_hosts for git.designhammer.net (since the IP address had changed to Bitbucket's).
  2. In each repo that had been cloned from git.designhammer.net, each developer had to edit .git/config to modify the clone URL. So what used to be git@git.designhammer.net:some-repo had to be changed to git@git.designhammer.net:designhammer/some-repo (note the addition of designhammer/). This makes sense, as the repo is now under the designhammer account on Bitbucket.
  3. Don't forget to also use Bitbucket's deploy keys if you are checking out the repo on a server for pushing code to an environment.

And that's it! The whole process — from decision to implementation — took just a few hours, and it was well worth the effort. I hope this guide will be useful to you if you decide to migrate as well. Let us know in the comments if you have any suggestions or tips to improve this guide.


Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.