→ Forking, Continued

Wednesday, January 21, 2009

David Welton has posted a thoughtful reply to my comment. Unfortunately, he missed my point. I can only assume this is due to a lack of clarity on my part. (My comment was very brief.)

I mentioned the Network Graph and Fork Queue but David mentioned neither. I think he doesn’t know what they are, probably because I didn’t explain what they are :)

So, in an effort to be more clear, let me propose an alternate workflow to David’s. He says, “Here’s a concrete example of how things might go wrong.” I see his example and think, “That’s a concrete example of how things have gone right.”

(I’m going to make this visual so you don’t have to take my word for it or keep jumping between here and GitHub to try it out.)

The Network Graph

root@fortrock:~# gem1.8 search -r actionwebservice

*** REMOTE GEMS ***

actionwebservice (1.2.6)
datanoise-actionwebservice (2.2.2)
dougbarth-actionwebservice (2.1.1)
nmeans-actionwebservice (2.1.1)

The problem is obvious: which actionwebservice should we use?

Well, we know three of those gems are on GitHub. And all three of the GitHub gems have higher versions than the Rubyforge gem. So let’s check GitHub first.

I go to http://github.com/search and search for actionwebservice. (Actually I do this from my LaunchBar template, but you get the idea.)

In the results, I see that the first actionwebservice appearing has the most forks and watchers, and was the most recently active.

We could stop right here and choose datanoise’s fork. But let’s be sure.

I click on the repo and arrive at http://github.com/datanoise/actionwebservice. I click on the Network tab.

I arrive at http://github.com/datanoise/actionwebservice/network and glance at the graph.

There are commits unique to certain forks, but datanoise has the most activity and the most recent commits.

At this point, there’s no doubt: datanoise is the most recent, most active version of actionwebservice. Will it always be? Who knows. But for now, this is the best choice.

The Fork Queue

We can take it a step further, too. We see there are unmerged commits – changes people have made which have not been pulled into datanoise. We can examine them straight from the Network Graph, or we can attempt to merge them into actionwebservice.

I fork datanoise’s actionwebservice using the ‘fork’ button, still on the Network Graph’s page:

Now I have my own version of actionwebservice.

Time to visit the Fork Queue. (Only people with write access to the repository see this tab.)

Okay, so it looks like a lot of the changes made will not apply cleanly.

If any of these commits had a green background, we’d be able to apply them right there on the site (as explained by the legend). But we can’t.

Pull Requests

Since we can’t apply the commits, we could send datanoise a message asking him to check over his Fork Queue and merge in the changes that look promising. We could do it ourselves, too, by resolving the conflicts. All we’d need is to clone our repository, add one of the others as a remote, then merge and fix the conflicts before pushing back to our version. After that we could even send datanoise a pull request, since we’ve done the work for him. Or just wait for him to check his Fork Queue and see that our changes are green.

I’m just going to delete my fork, though.

Keeping Current

Even ignoring the forking and the Fork Queue, the point is this: it’s not hard to see which project is the most active. Yes, we (GitHub) need to make it more clear. We want to say “this is the fork you’re looking for” on the first page you see. And we want that to change as the most active, latest fork changes. But, for the time being, you can figure that all out with a single click.

What happens when it does change, though? Perhaps datanoise will lose interest and someone else will take up development. That’s the beautiful part, and that’s why you just can’t do GitHub without Git (or any equally powerful DVCS): switching the remote and pulling in changes from the new repository is trivial. Git doesn’t care where you pull from. It is not married to a remote URL in the same way a centralized VCS like Subversion is.

Imagine hitting the datanoise repository and being informed “this may not be the most active repository in the network. Check Person X’s.” Switch your remote to the new one, pull, and you’re up to date. This is the type of information the Network Graph makes available, we just need to make it more visible and plain. (Heck, maybe that message could be printed out when you git pull from an inactive remote.)

For instance, hitting dougbarth’s actionwebservice fork and checking the Network Graph makes it obvious that datanoise is the repo we want:

If we were previously using dougbarth’s fork it would be clear that datanoise’s is the one to watch in the future.

Moving Forward

It may seem strange, and perhaps even like a lot of work. “Why should I have to check to see which is the most current? In the old model, there’s always a canonical repository.”

In the old model, actionwebservice wouldn’t have made it past 1.2.6. Welcome to distributed version control.

→ Linux vs Classic Dev Style

Tuesday, January 20, 2009

I tried to leave this as a comment on Developer > Project, or Project > Developer(s)? but the form errored and I couldn’t find a contact email address. Here it is:

GitHub lets you do Linux-style fork development, or classic SourceForge style development. The difference is you have the choice.

Using the Network graph you can easily see which fork in a Linux-style network has the most recent activity. It’s one click away from any repository’s home page, but we’re working on better surfacing and summarizing the information.

As for lazy developers not requesting you pull in changes, the Fork Queue lets you see unmerged changes in forks and even lets you merge them in from the web interface.

We’re constantly working to improve our tools and the ways you can manage your projects, as well.

→ TextMate Minor Mode

Tuesday, December 02, 2008

TextMate Minor Mode is an Emacs minor mode that emulates some awesome TextMate features.

Like ⌘T (find file in project).

And ⇧⌘T (go to symbol in file).

And more! Really, the README says it all.

Installation:

$ cd ~/.emacs.d/vendor
$ git clone git://github.com/defunkt/textmate.el.git

In your emacs config:

(add-to-list 'load-path "~/.emacs.d/vendor/textmate.el")
(require 'textmate)
(textmate-mode)

Or just grab the elisp: textmate.el

TextMate Minor Mode was written for Aquamacs but works great on console Emacs, CVS Emacs.app and Carbon Emacs. Try it today!

→ Why Lisp Failed

Monday, December 01, 2008

Emacs.

Writing Lisp without Emacs is just too painful. If your language depends on specific features of a specific editor, you better be a big company like Sun or Microsoft with the mad moneys. Otherwise forget it.

→ Learning Your Editor

Wednesday, November 19, 2008

Text editors should take a lesson from video games. In many games, you have access to subset of total weapons, powers, whatever. As you advance and master the basic weapons, more weapons become available to you. By the end of the game you have direct experience with all or most of the weapons – from basic to advanced.

How many times have you done something cool or strange in Vim only to think, “How did I do that?” video-game-mode would be a fun way to learn an editor: start with the basic commands and unlock more as you progress.

→ Singin' Singletons

Tuesday, November 18, 2008

There’s stuff I just don’t understand. David Bowie, for instance. Or the Southern Hemisphere. But nothing quite boggles my mind like Ruby’s Singleton. Because really, it’s totally unnecessary.

Here’s what they want you to do with your code:


require 'net/http'

# first you setup your singleton
class Cheat
  include Singleton

  def initialize
    @host = 'http://cheat.errtheblog.com/'
    @http = Net::HTTP.start(URI.parse(@host).host)
  end

  def sheet(name)
    @http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.instance.sheet 'migrations'
Cheat.instance.sheet 'yahoo_ceo'

But that’s crazy. Fight the power.


require 'net/http'

# here's how we roll
module Cheat
  extend self

  def host
    @host ||= 'http://cheat.errtheblog.com/'
  end

  def http
    @http ||= Net::HTTP.start(URI.parse(host).host)
  end

  def sheet(name)
    http.get("/s/#{name}").body
  end
end

# then you use it
Cheat.sheet 'migrations'
Cheat.sheet 'singletons'

Any why not? The API is more concise, the code is easier to test, mock, and stub, and it’s still dead simple to convert into a proper class should the need arise.

→ Pretty Fixtures

Tuesday, November 18, 2008

# in whatever test helper you use
class Test::Unit::TestCase
  def defunkt
    users(:defunkt)
  end

  def github
    repositories(:github)
  end
end

# in your tests
context "A user" do
  test "belongs to a repository" do
    assert_equal defunkt, github.user
  end
end

Somethin’ like that.

→ Sugar

Thursday, October 30, 2008

The console is part of your app. Treat yourself right.

→ Good Homes Found

Wednesday, October 29, 2008

After putting out the call, a few developers interested in taking up sad, abandoned projects of mine stepped forward.

Thanks to the following for giving these projects good homes:

→ Good Homes Wanted

Wednesday, October 22, 2008

The following projects need a good home. Interested in taking over? Let me know.