Josh SusserJosh Susser
svn to git protips
edit Posted by Josh Susser on Wednesday September 30, 2009 at 11:20AM

When you're moving a codebase from subversion to git, here are a few things that make the move go a bit more smoothly.

In the svn project, you can discover some things you'll need to adjust in git after the import.

Show all files being ignored

svn propget -R svn:ignore .

Add these files to the .gitignore file at your project root, or in appropriate subdirectories. I prefer keeping it all in one place at the top level.

Show all externals

svn propget -R svn:externals .

You'll either have to switch to using a submodule in git, or just pull the files into your project if that's not possible for some reason.

Find all empty directories

find . -type d -empty
touch /path/to/empty/dir/.gitkeep

Since git doesn't keep empty directories, you can add a .gitkeep file to empty directories that you don't want to go away. Some people add a .gitignore file to keep the directory around, but that sounds totally backwards to me. You want to keep it, not ignore it.

By the way, if you are already ignoring dir/*, that will ignore the .gitkeep file as well. Make sure it isn't missed by adding !.gitkeep to the end of your .gitignore file.

Find all authors

If you want to properly attribute commits, you'll need to set up an authors file. But if you miss any authors, the clone will stop and complain. You can discover all the svn users that you need to put in the authors file with this command:

svn log | grep -E 'r[0-9]+ ' | cut -d\  -f3 | sort | uniq

init + fetch > clone

If git svn clone doesn't complete, try doing the init/fetch as separate operations. The clone subcommand is pretty much just doing an init followed by a fetch, but I've found that if the clone fails, doing the commands separately can have better success.

Alex ChaffeeAlex Chaffee
git unadd
edit Posted by Alex Chaffee on Wednesday September 02, 2009 at 03:16PM

Sometimes I accidentally git add files. Or more often, I do git add . and get a huge changelist and then realize I want to move certain files to a different changelist or a different branch. I could do a git reset which, absent --soft or --hard, pulls all the changes out of the index (aka dircache aka staging area) but leaves them in the filesystem (aka working tree). But wouldn't it be nice to leave all the files in the index except the few I want to keep out?

Alex ChaffeeAlex Chaffee
git config push.default matching
edit Posted by Alex Chaffee on Thursday June 04, 2009 at 04:29PM

Upgraded to git 1.6.3 yet? You should, and Jason Rudolph says why (and if you're on a Mac, Rob Sanheim says how.)

Sadly, after you do upgrade, when you start doing "git push", your console will start to be littered with the following oddly patronizing message:

warning: You did not specify any refspecs to push, and the current remote
warning: has not configured any push refspecs. The default action in this
warning: case is to push all matching refspecs, that is, all branches
warning: that exist both locally and remotely will be updated.  This may
warning: not necessarily be what you want to happen.
warning: 
warning: You can specify what action you want to take in this case, and
warning: avoid seeing this message again, by configuring 'push.default' to:
warning:   'nothing'  : Do not push anything
warning:   'matching' : Push all matching branches (default)
warning:   'tracking' : Push the current branch to whatever it is tracking
warning:   'current'  : Push the current branch

While I'm generally in favor of verbose warnings, this one is kind of bizarre. Essentially, it's saying, "Warning! The command you just ran will continue to operate exactly as it did before!" Guys, telling us about new options is great but that's what release notes are for.

Worse, they don't provide keystroke-level instruction beyond the offhand gerund "configuring" on how to shush it. Here's the result of my 8-minute speluking inside the output of "git help config":

git config push.default matching

[Or, thanks to Alastair Brunton below

git config --global push.default matching

]

There, now, that wasn't so hard after all, was it?

Jeff DeanJeff Dean
Testing capistrano recipes with cucumber
edit Posted by Jeff Dean on Sunday April 05, 2009 at 10:29PM

In this post, I'll show you how to set up end-to-end Capistrano testing using Cucumber. I've extracted this from the cucumber features I wrote for a gem I'm building named auto_tagger. To fully test capistrano recipes, your tests will have to:

  • Create a local git repository
  • Create a local app with a config/deploy.rb file
  • Push the app to the local repository
  • Run cap deploy:setup from the app (which will setup a directory inside your local test directory)
  • Run a cap deploy from the app (which will deploy to your test directory)
  • Assert against the content of the deployed app in the test directory

Background - Capistrano recipes are almost never tested

Looking around online, I couldn't find a single list of capistrano packages that has an automated test suite, even ones from some big hosts. It's no surprise that Capistrano tasks are seldom tested - testing capistrano recipes is hard, and even when you do test them, there are still so many variables in real-life deploys that you can't account for everything.

It's like Rummy said:

There are known knowns. There are things we know that we know. There are known unknowns. That is to say, there are things that we now know we don’t know. But there are also unknown unknowns. There are things we do not know we don’t know.

from wikipedia

However, there are some things you can do to stave off the "known unknowns". For example, you know that someone might forget to set an important variable in their cap task and you know they might be using cap-ext-multistage. For these kinds of examples, Capistrano testing can give you much more assurance that a bug in your recipe is less likely to rm -rf /* on your remote machine.

AutoTagger is a gem that helps you automatically create a date-stamped tag for each stage of your deployment, and deploy from the last tag from the previous environment.

Let's say you have the following workflow:

  • Run all test on a Continuous Integration (CI) server
  • Deploy to a staging server
  • Deploy to a production server

You can use the autotag command to tag releases on your CI box, then use the capistrano tasks to auto-tag each release.

Ben WoosleyBen Woosley
The Multitalented 'git add' - rm-ing files and selectively staging changes
edit Posted by Ben Woosley on Friday February 13, 2009 at 03:01PM

A problem I had as a git newbie, and one I've seen others struggle with, is the problem of how to conveniently stage the deletion of files which are already deleted from disk, but aren't yet reflected in the index? That is, without 'git rm'ing them one at a time or using some other hack (e.g. 'git ls-files --deleted') to do so.

The answer is 'git add'

Jeff DeanJeff Dean
Moving from Subversion to Git
edit Posted by Jeff Dean on Thursday October 16, 2008 at 01:58AM

Moving from Subversion to Git

We recently moved our project from subversion to git, and so far the move has gone very smoothly. The following post will detail what we did to make the move.

Our setup

For this project there 2 pairs working and we have 6 machines and one hosted service:

  • Two Mac OSX workstations with IDEA
  • One continuous integration server running Cruise Control
  • A staging server running a 2-year old version of Ubuntu
  • A subversion server
  • A production server hosted on Engine Yard
  • A Github account with the ability to create private repositories

The goal was to have one pair continue to work while the migration from svn to git was happening.