Tech Blog :: on Git: how to preserve GitHub repositories for existing modules

Feb 25 '11 3:13pm
Tags on Git: how to preserve GitHub repositories for existing modules

I've been keeping all my code on GitHub, waiting for to move from CVS to Git. Well, it just did! No more bitching about the lousy CVS process, time to start maintaining my module releases again.

I want to keep my GitHub repositories' histories, of course. (Keeping the actual code on GitHub isn't critical, it's the commit/branches/tags that are important.) The new repositories on d.o were copied from the old CVS repositories, which contained (because I was lazy / holding out for Git) only final releases at best, or nothing at all, so I want the GitHub history to take precedence.

Git is "distributed," meaning the full repository is cloned everywhere it's used, including multiple "remotes." (This is unlike CVS or SVN, where there is a single remote server, and local "checkouts.") Anyway, this isn't the place for a Git tutorial (see the great [free] Pro-Git book to learn Git and some of my past Git tricks). I had assumed when d.o moved to Git, I could simply add a new remote and it would work automagically. It almost does, but needs a little extra work.

There is some official d.o documentation for Copying your repository onto from an existing repository. It clones the GitHub repo as a "mirror" and pushes the merged repo to d.o. This didn't work for me, for some reason. Maybe it'll work for you - try it first and see if it does. This worked for me instead.

This is all done through the terminal, from the directory where I've cloned my existing GitHub repository. My remote name for Github is origin and the branch is master (the standard convention). I'm going to leave GitHub at origin and add as drupal. To get the exact path to your repository, go to the Git Instructions tab in your project page. (I assume you've already agreed to the new TOS and set up SSH keys as it explains there.)

Add a new remote to the existing (but different) d.o repository:
git remote add drupal

(A digression: if you try at this point, git push drupal master, it'll throw an error -

 ! [rejected] master -> master (non-fast-forward)

- because the repository histories are different and can't be merged normally.)

Instead, pull the git.d.o branch alongside your existing one. (Note that the new 'drupal' remote has its own 'master' branch separate from the one we want. Hence we're fetching and not pulling.)
git fetch drupal

Then merge, but keeping the existing history ("ours") as the correct version:
git merge remotes/drupal/master --strategy=ours

One problem at this point: the git.d.o migration made a good change: "Stripping CVS keywords" (like $Id$). That's now gone, because we've dismissed the d.o history. So we get it back with a cherry-pick: git log shows the commit hash from the migration, so copy the start of the hash, and re-apply it:
git cherry-pick ####.

Check your code to make sure it's good... then
git push drupal master
And it's all up!

To create a tag for a new release (example):
git tag 6.x-1.0-alpha1
git push drupal 6.x-1.0-alpha1

(Interested in any feedback saying why this is stupid / why the other approaches should have worked / why this is causing the d.o infrastructure horrible damage... all I know is, it seemed to work for me.)

The documentation you linked to above worked okay for me.