Using SVN repositories as git submodules

With the Subversion VCS, one way to import external modules or libraries into a code tree is by defining the svn:externals property of your repository. Subversion will then check out the specified revision (or the latest revision) of the other repository into your source tree when checking out your code.

Submodules are basically the same thing in the “git” world.

And since git can talk to subversion repositories with git svn, we should be able to specify a third-party SVN repository as a submodule in our own git repository, right? Sadly the answer is currently: No.

Here is a workaround that I have been using to at least achieve a similar effect, while keeping both SVN and git happy. This assumes that you have a local git repository that is also available somewhere else “up-stream” (such as github), and you want to import an external SVN repository into your source tree.

1: Add a tracking branch for SVN

Add a section referring to your desired SVN repository to your .git/config file:

(...)
[svn-remote "product-details"]
    url = http://svn.mozilla.org/libs
    fetch = product-details:refs/remotes/product-details-svn

Note that in the fetch line, the part before the colon refers to the branch you want to check out of SVN (for example: trunk), and the part after that will be our local remote branch location, i.e. product-details-svn will be our remote branch name.

Now, fetch the remote data from SVN, specifying a revision range unless you want to check out the entire history of that repository:

git svn fetch product-details -r59506:HEAD

git will check out the remote branch.

2: clone the tracking branch locally

Now we have a checked-out SVN tracking branch, but to use it as a submodule, we must make a real git repository from it — a branch of our current repository will keep everything in one place and work as well. So let’s check out the tracking branch into a new branch:

git checkout -b product-details-git product-details-svn

As git status can confirm, you’ll now have (at least) two branches: master and product-details-git.

3: Import the branch as a submodule

Now let’s make the new branch available upstream:

git push --all

After that’s been pushed, we can import the new branch as a submodule where we want it in the tree:

git checkout master
git submodule add -b product-details-git ../reponame.git my/submodules/dir/product-details

Note that ../reponame.git refers to the up-stream repository’s name, and -b ... defines the name of the branch we’ve created earlier. Git will check out your remote repository and point to the right branch automatically.

Don’t forget to git commit and you’re done!

Updating from SVN

Updating the “external” from SVN is unfortunately a tedious three-step process :( . First, fetch changes from SVN:

git svn fetch product-details

Second, merge these changes into your local git branch and push the changes up-stream:

git checkout product-details-git
git merge product-details-svn
git push origin HEAD

And finally, update the submodule and “pin it” at the newer revision:

git checkout master
cd my/submodules/dir/product-details
git pull origin product-details-git
cd ..
git add product-details
git commit -m 'updating product details'

Improvements?

This post is as much a set of instructions as it is a call for improvements. If you have an easier way to do this, or if you know how to speed up or simplify any of this, a comment to this post would be very much appreciated!

Categories: Mozilla Crosspost, OSU OSL Crosspost, Tech Talk | Tags: ,

Firefox 3.6 RC1

The Firefox 3.6 Release Candidate 1 has been released and its new features are just fantastic! From the first-run page:

Go check it out.

Categories: Mozilla Crosspost, OSU OSL Crosspost, Tech Talk | Tags:

Partial ‘svn dcommit’ with git

Here at Mozilla, a bunch of webdevs use git svn instead of plain Subversion to interact with our svn repositories — mostly because of in-place branching, better merging, and all these things that make a dev’s life happier.

As you probably know when reading this article, you push all uncommitted changes to the remote svn repository by typing git svn dcommit. This will take your last, say, five commits, push them to SVN, and mark them locally as committed. But what if you only want to dcommit some of your changes?

(If you don’t need explanations, jump straight to the summary).

Step 1 (optional): Reorder commits

I am not going to go into a lot of detail on interactive rebasing (git rebase -i), but to start off, make sure your commits are ordered, so that the ones you do want to commit to SVN are before the ones you do not want to push up-stream for now. Example: If in the following history, you want to commit all changes but a023fea, you want to rebase your commits so a023fea is last:

In git rebase -i HEAD~4, change…

pick 07c26c5 some de L10n
pick a023fea adding free-text messages to localizer dashboards
pick 8597f47 adding featured collections as l10n category
pick 19f3df3 making existing localizer pages work with amo2009 layout

… to…

pick 07c26c5 some de L10n
pick 8597f47 adding featured collections as l10n category
pick 19f3df3 making existing localizer pages work with amo2009 layout
pick a023fea adding free-text messages to localizer dashboards

Make sure to resolve any merging problems that might occur due to the reordering.

Step 2: Step in between commits

To only push the desired commits to svn, execute another git rebase -i and mark the last desired commit for editing (by changing pick to edit):

pick 07c26c5 some de L10n
pick 8597f47 adding featured collections as l10n category
edit 19f3df3 making existing localizer pages work with amo2009 layout
pick a023fea adding free-text messages to localizer dashboards

When exiting the editor, git will drop you off after the marked commit, but before the one you don’t want, as a quick look at git log can tell you.

Step 3: dcommit desired changes

After making sure this is really what you want, just execute git svn dcommit as usual and watch git push all desired changes to SVN, while omitting the rest.

Step 4: Fast-forward to HEAD

When the dcommit is done, remember we are still in the middle of a rebase, so just run git rebase --continue to fast-forward to the HEAD of your branch. Again, a quick look at git log can reassure you that only the changes you wanted to have been pushed to SVN.

Success!

Summary: Quick cheat sheet

Here’s a quick cheat sheet for you (and me) to come back to in case you forget:

  • Reorder commits (git rebase -i HEAD~4) so that the undesired ones are after the ones you want to push
  • In your commit history, jump right after the last wanted commit by marking it for editing in git rebase -i
  • git svn dcommit
  • git rebase --continue

Categories: Mozilla Crosspost, OSU OSL Crosspost, Tech Talk | Tags: , , ,

Mac Superdrive Noise-B-Gone Update?

When skimming through my pending Mac OS X upgrades this morning I noticed one saying:

This update eliminates the noise made by the optical disk drive during system startup and wake from sleep on MacBook computers.

Wow. As long as I’ve been using a Mac, the sweep-sweep noise has been characteristical for a Mac startup sound, reminiscent of the floppy drive seek sound computers made when they still came with floppy drives (yes, dear children, I am that old).

I wonder what this was for in the first place. Maybe to find out reliably if there is a disc in the drive already? <crystal ball>Possibly, the operating system did not check again and just relied on the hardware status flag being set correctly on startup, and if it was wrong, evil things could happen?</crystal ball> And now, almost suddenly, the Mac engineers found out that it is unnecessary altogether? The wonders of Snow Leopard.

What comes next? Removing the gong on boot to avoid Mac-obsessed college kids from making fools of themselves during lectures? ;)

Zombie-MacBook Wakes Itself up from Sleep

Zombies Invade San Francisco!For the longest time, I was sending my laptop to “hibernation” mode every night. Why? Not because I particularly mind the minute power consumption it might have while sleeping, but because it would randomly wake up during the course of the night. My “zombie laptop” would particularly annoy me because it’d log back into my messaging service in my absence (thus prompting people to think I am awake at 3 a.m.), get unnecessarily warm (due to its being closed), and when I opened it back up, it’d not switch its monitor back on (due to a feature that OS X calls “clamshell mode”).

Today, I had enough, and after a little more googling, I stumbled across a comment in a macosxhints article mentioning Bluetooth settings: Apparently, there’s a setting for letting bluetooth devices power your Mac up from sleep. As I have a bluetooth-based wireless Mac keyboard, I tried out switching that setting off — and long story short, it seems to have worked.

If you have the same problem, uncheck the following box in System Settings / Bluetooth / Advanced Settings to give it a shot:

Bluetooth Wake

Happy zombie-Mac killing!

“Assign to me” Jetpack

Just recently, my colleague oremj published a bookmarklet making “assign this bug to me” a one-click operation in bugzilla.

Obviously, bookmarklets are fun and games, but Jetpacks are even more awesome, so I went ahead and wrote one that adds an “assign to me” button next to the assignee field:

Assign-to-me button jetpack

You can find and install the jetpack through my jetpacks page on github.

Firefox on the Coliseum

This photo is not photoshopped:

Colosseo

The Mozilla Italia team projected a Firefox wordmark onto Rome’s most famous landmark — and on many other places all over the city. Make sure to check out the picture in its full glory over on flickr.

Picture CC by-sa licensed by nois3lab on flickr.

Categories: Mozilla Crosspost, OSU OSL Crosspost, websights | Tags: ,

Code Cosmetics With Komodo and vim

The source code for the Mozilla Add-ons project tries to follow the PEAR Coding Standards. One of these standards is to use 4 spaces per level of indentation, and no tabs.

Over time, unfortunately, some files start to contain a significant amount of mixed-up indentation (both from badly set-up IDEs and third-party contributions that came with tab indentation but went un-noticed). That’s both tedious and error-prone to fix by hand.

A similar problem poses trailing whitespace. While it’s just annoying in general, especially in HTML template files, it also increases page size unnecessarily by leading to more bytes transmitted on the wire, with no benefit to neither the users nor the developers.

Luckily, there are two quick fixes for these problems in both the editor vim and my IDE of choice, Komodo:

To remove tabs and replace them with spaces…

  • in Komodo, select a code block, then click Code -> Untabify Region.
  • in vim, type :%s/\t/    /g (those are four spaces) — or, as oremj points out in the comments, you could just to :retab .

And to wipe out trailing whitespace…

  • in Komodo, in Preferences -> Editor / Save Options, activate the option “Clean trailing whitespace and EOL markers”. Then open your document of choice and just save it again. However, when writing patches, you might want to refrain from keeping this option on at all times: It might result in confusion if a lot of lines are touched that do not have anything to do with the current patch. I wish there was a one-time way to run this, instead of a config option.
  • in vim, type :%s/\s\+$//g which the regex-savvy among you have quickly decyphered as: “in the entire document, replace all one or more whitespace characters that are followed by a line ending with the empty string”.

Happy cleaning!