Cleanly Migrate Your Subversion Repository To a GIT Repository

So you're ready to ride the GIT train eh? But what about all those projects in your subversion repository? Sure you could just use git-svn but what you really want is to cleanly move that repository and all its history to a nice new GIT repository.

Luckily it's not that hard. For this example I'm going to use my_blog as the application name you're porting to a GIT repository. We're basically going to just initialize a new GIT repository, point it at your SVN repository, and suck in your code and history while remapping the users to GIT users. We'll then just clone THAT repository to have a clean GIT repository free of SVN clutter.

The first thing we need to do is create a users file that maps all your SVN users to your GIT users. Just make a file on your Desktop named 'users.txt'. Map the users using this format:

jmaddox = Jon Maddox <jon@gmail.com>
bigpappa = Brian Biggs <bigpappa@gmail.com>

Simple. Now here are the commands you'll run. I'll explain them below.

mkdir my_blog_tmp
cd my_blog_tmp
git-svn init http://code.yoursite.net/my_blog/trunk/ --no-metadata
git config svn.authorsfile ~/Desktop/users.txt
git-svn fetch

The first two are self explanatory, we're making a new directory for the temporary repository. The second command initializes the directory as a git-svn hybrid thing and points the origin at your SVN repository. The flag, --no-metadata, tells GIT to leave all the SVN details behind (not the commit log). The fourth command tells GIT to remap all the SVN users to GIT users when it sucks down the source and history. The last command actually does the fetching.

Ok, so now after a few LONG minutes, your source is all there. Do a git log to see that your users have been mapped. Sweet!

Now you just have one last step. You need to clone this repository. Why do we do this? When doing a normal git clone it will take everything we want from the temporary repository, while leaving behind all the SVN cruft that was there to support the git-svn stuff.

git clone my_blog_tmp my_blog

Boom! You're done. Now you have a super clean GIT repository all ready to use.

Popularity: 54% [?]

    Categories: GIT, Snippets     17 Comments »

GIT It?

While working today I think I heard GIT mentioned on every form of communication I use daily. It was mentioned in several IRC channels, on twitter a ton, in an email, over IM, and a couple of new posts in my feeds. It has become obvious that GIT has hit the early adopter phase.

I'm not going to sell GIT or even try to explain why it's so great. There are tons of places online that already do that. I'm just going to share a couple stories.

Who Gives a Crap, I Gotta Get Work Done

This new source code management software that seems to be gaining a HUGE amount of steam first popped on my radar early last summer. I contemplated playing with it, but like most things, I skipped it. I figured as a single developer, it wouldn't mean much to me. I code,commit, iterate. "What do i need with fancy branching?" I said. But @peterc replied with my answer. I just didn't get it then.

Months went by as I used SVN like everyone else. I was just happy with versioned code, that's about all that SVN did for me.

RubyConf 2007

As I was outside with the rest of the Ruby Smoking Crew, I got Chris Wanstrath, unofficial GIT ambassador, to try to sell me on it. He started with the normal branching pitch, and I stoppped him.

"I don't branch".

"Because you don't use GIT".

BOOM. It hit me. I don't branch because branching with SVN sucks so much fucking arse that it's just not worth it. CERTAINLY not for changes that take only a few hours. With SVN you hang out on trunk and make your thousands of commits. Forget if you want to try something wacky real fast, you'd have to branch it! And thats just a whole lot of work.

Fast Forward a Few Days.

I'm sitting in a cube at Yahoo!. I'd been given a task a few days earlier. I was working on it and hit a stopping point. I needed to make a huge sweeping change. BUT, two hours later, I had to demo it to a room full of Yahoo! people I had never even met. AND they expected it to work. I knew my changes were going to break the whole app for a little while.

Ok, so first off, this project was neither IN a repository, nor did I even have access to one. I'd only been there for like two days. So I could copy my source directory and file it away for the demo, or... I could finally throw GIT on my laptop and try it out! So I installed GIT, initialized my rep. Branched it...whoa what? Thats it. git checkout -b new_model? Thats it?! SICK.

I continued my work and when it came time for the demo I just used git checkout master and voila, I was back to my fully working copy. I finally 'got' GIT. At least the branching part. Not only is it easy to branch, you can branch locally. And by locally, I mean privately. So if you want to try something weird and crazy out, you don't need to worry about making a new branch at the central repository, just branch it locally and go to town. If it worked out, merge it back into master. If it doesn't, just dump it. Now, like most GIT users, I don't even work directly on master.

Ok, thats my story. I guess the moral is, you're never going to get why something is good for YOU until YOU use it. Everyone takes different things away from products, especially when you're talking about productivity.

Popularity: 17% [?]

    Categories: GIT, Tools     1 Comment »

Mustache is Real

So I finally got around to getting legit and filed my papers. I'll now be operating under the name Mustache, Inc. But mainly just Mustache. WTF? Mustache? Why?

Why would I name my company Mustache? Well, why not. I came up with the logo and liked it, and wanted something a bit abstract. Plus it is going to work well as a first line of defense for boring stuck up clients. If you can't work with a company named Mustache, then Mustache can't work with you.

If you've met me, you'd know I'm a pretty laid back guy. I don't kiss ass and I don't bullshit. I let my work and commitment to projects speak for itself. I've tried to convey this with initial consults with clients. I tend to give them "100% Maddox" during these meetings and lay it all on the table. So far it has worked out great. It's amazing what happens when you operate a business as an honest and transparent person. It actually works! Imagine that!

So let it be known, I'm officially available for hire. Check out the site and let me know what you think.

http://www.mustacheinc.com

Popularity: 15% [?]

    Categories: Rails, Ruby     3 Comments »

Spec Out Your Cookies with Rspec

Here's something that got me this weekend and I couldn't find much info on it anywhere. So like my Internet taught me, I'm sharing.

links_controller.rb
cookies[:phone] = params[:phone]
links_controller_spec.rb
it "should save the phone number in a cookie" do
  @my_cookies = mock('cookies')
  @my_cookies.stub!(:[]=)
  controller.stub!(:cookies).and_return(@my_cookies)
 
  @my_cookies.should_receive(:[]=).with(:phone, '804-755-7555')
 
  do_post
end

Here I'm making the expectation that a cookie will be set with the key of 'phone' and a value of a passed in parameter. My do_post method takes care of the post and passes in the parameter :phone => '804-755-7555'.

Popularity: 14% [?]

    Categories: Rails, Snippets, Testing     No Comments »

Put Your PHP on Port 3000 With Lighttpd

While most of my work these days is in a Ruby and Rails environment, I still get my hands dirty with PHP every now and again.

When working with web projects I practically require the ability to use absolute links for static content. Because of this, I usually have to host a PHP project under Apache and create a virtual name, oh and make a fake host entry in my hosts file. Blegh.

This usually sucks even more when I throw in the fact that my project is under some kind of source control (which is usually always the case). So what is a frustrated developer to do?

Well, the only reason this is annoying is because I don't have to deal with it in my script/server world of Rails development. So I solved my litle PHP problem by borrowing from what I learned with Rails.

Instead of developing PHP apps under Apache, I installed Lighttpd and fire off an instance whenever I need to do work on the app. Very simply I added a lighty config file under APP_ROOT_/config and when I want to work on my PHP app, I just start lighty. Booom. Now I have my app running at localhost:3000. Just like my Rails apps, so my fancy bookmark in my bookmark bar works for both my PHP and Rails projects. Now that DRY!

So, how do you get it going like this? First off, all of these instructions were done in OS X 10.5 Leopard, so be warned.

Roll Your PHP

You need to roll your own PHP in order to get support for php-cgi. Do this:

mkdir src
cd src
wget http://us.php.net/distributions/php-5.2.5.tar.gz
tar xfz php-5.2.5.tar.gz
cd php-5.2.5
./configure --enable-fastcgi --enable-discard-path --enable-force-redirect --with-zlib
 --with-xml --with-mysql=/usr/local/mysql --prefix=/usr/local/php5-fcgi --disable-cli 
 --enable-memory-limit --with-layout=GNU --with-regex=php
 
make
sudo make install

Pretty basic. Download, configure, make, and install PHP.

Next, rename the php binary, use tab complete I think the XXX part is different per install(?)

sudo mv /usr/local/php-cgi/bin/php-cgi.XXX /usr/local/php-cgi/bin/php

Lighttpd

Ok, I'm not a big fan of MacPorts, but I was having so much trouble getting Lighttpd installed on Leopard, that I had macports do it for me. So, go install macports first and:

sudo port -d selfupdate // this errored the first time, did it again and all was well
sudo port install lighttpd

All the Rest

Ok, now you need to fix a small little problem with MySql and your new PHP. The new PHP may not see your MySql stuff correctly, so do this:

sudo mkdir /usr/local/mysql/lib/mysql
sudo cp /usr/local/mysql/lib/libmysqlclient.15.dylib /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib

Set Up Your App

Ok, you're all set up. Now you just need to add a lighttpd config file to your app. Create APP_ROOT/config/lighty.conf with this:

 
  server.port = 3000
 
  # server.errorlog    = CWD + "/log/lighttpd.error.log"
  # accesslog.filename = CWD + "/log/lighttpd.access.log"
 
  server.modules = ( "mod_rewrite",
                     "mod_access",
                     "mod_fastcgi",
                     "mod_userdir",
                     "mod_accesslog" )
 
 
  # If no file is specified, what to look for?
  index-file.names = ( "index.html", "index.php" )
 
  # Run the server under the user-name "www" for security purposes
  # To bind to port 80, the server must be called by root user, but we don't want
  # the server to have free run of the box, so it runs as "www"
 
 
  # Set up the appropriate MIME type mappings
  mimetype.assign             = (
    ".pdf"          =>      "application/pdf",
    ".sig"          =>      "application/pgp-signature",
    ".spl"          =>      "application/futuresplash",
    ".class"        =>      "application/octet-stream",
    ".ps"           =>      "application/postscript",
    ".torrent"      =>      "application/x-bittorrent",
    ".dvi"          =>      "application/x-dvi",
    ".gz"           =>      "application/x-gzip",
    ".pac"          =>      "application/x-ns-proxy-autoconfig",
    ".swf"          =>      "application/x-shockwave-flash",
    ".tar.gz"       =>      "application/x-tgz",
    ".tgz"          =>      "application/x-tgz",
    ".tar"          =>      "application/x-tar",
    ".zip"          =>      "application/zip",
    ".mp3"          =>      "audio/mpeg",
    ".m3u"          =>      "audio/x-mpegurl",
    ".wma"          =>      "audio/x-ms-wma",
    ".wax"          =>      "audio/x-ms-wax",
    ".ogg"          =>      "application/ogg",
    ".wav"          =>      "audio/x-wav",
    ".gif"          =>      "image/gif",
    ".jpg"          =>      "image/jpeg",
    ".jpeg"         =>      "image/jpeg",
    ".png"          =>      "image/png",
    ".xbm"          =>      "image/x-xbitmap",
    ".xpm"          =>      "image/x-xpixmap",
    ".xwd"          =>      "image/x-xwindowdump",
    ".css"          =>      "text/css",
    ".html"         =>      "text/html",
    ".htm"          =>      "text/html",
    ".js"           =>      "text/javascript",
    ".asc"          =>      "text/plain",
    ".c"            =>      "text/plain",
    ".cpp"          =>      "text/plain",
    ".log"          =>      "text/plain",
    ".conf"         =>      "text/plain",
    ".text"         =>      "text/plain",
    ".txt"          =>      "text/plain",
    ".dtd"          =>      "text/xml",
    ".xml"          =>      "text/xml",
    ".mpeg"         =>      "video/mpeg",
    ".mpg"          =>      "video/mpeg",
    ".mov"          =>      "video/quicktime",
    ".qt"           =>      "video/quicktime",
    ".avi"          =>      "video/x-msvideo",
    ".asf"          =>      "video/x-ms-asf",
    ".asx"          =>      "video/x-ms-asf",
    ".wmv"          =>      "video/x-ms-wmv",
    ".bz2"          =>      "application/x-bzip",
    ".tbz"          =>      "application/x-bzip-compressed-tar",
    ".tar.bz2"      =>      "application/x-bzip-compressed-tar"
   )
 
 
  server.document-root = CWD
 
  fastcgi.server = ( ".php" => ("localhost" => (
                       "bin-path" => "/usr/local/php5-fcgi/bin/php", # path to php binary
                       "socket" => "/tmp/php.socket"
                   )))

Now at the root of your app run:

lighttpd -D -f config/lighty.conf

Boom, now you're deving with port 3000. Plus, your app isn't constantly available and just sitting there. When you need to work on it, fire it up, work, and shut'r down.

Popularity: 11% [?]

    Categories: PHP     3 Comments »
    Tags: