Thursday, January 29, 2009

Figuring out a branching strategy

To be honest, before I started working at Frogmetrics, I didn't know how project branches were managed. I was working at a research lab, and most of what we did was prototyping. After we demonstrated that it worked, we threw it over a wall, and then it was someone else's problem (poor them). A lot of the time, I was doing work on my own, so there was no (perceived) need for source control. The only time we used source control was when I was working on the New Horizon spacecraft. And even then, someone else managed the branches. Because it was SVN, we all mainly worked off trunk.

Until recently, I never contributed to an open source project either. Therefore, I really had no idea when to branch. So when we started working on the analytics, we really had no idea what a good branching strategy would be.

Googling didn't help, because either everyone else doesn't call it "branching strategy", or everyone already knew how to do it. I eventually figured something out though.

Last week, after talking to AJ of Scoopler about git, he ended up asking about branching strategy. It became apparent that branching strategy wasn't an obvious thing, so I decided to write something here. This is obviously not the only way to do it, so if you have other suggestions, by all means, comment.

At first, we didn't know what we were doing. We knew that we wanted to have a branch that had the same code on the production server, and another branch where we're working on the 'next' version. So we had a branching strategy that looked like this:

As you can see, we branched every time we deployed weekly. This gave us the option of doing bug fixes on the every deploy version, while keeping a working branch. However, this was a terrible way to do things. This branching strategy required you to keep merging back bug fixes that you had made earlier. In addition, we were using bug tracking software to track all the issues from week to week, which results in much ticket shuffling and overhead.

Now, we're doing this. Locally, we still branch for every feature that we're working on. And when there's a major set of features that need to be implemented by more than one developer, we create a remote branch for it that we push and pull to/from.

Thus, we're treating master as the golden copy of the code base. It is always deploy-able, passes all tests, and is perfect code as we know it. This allows us still the advantage of doing bug fixes and deploying independent of what features are currently on deck or in the hole, and yet we don't have to do merges every time are about to do a new version. We simply (and somewhat arbitrarily) tag versions as we go along, and only merge feature branches back. When we can, we rebase the branches to keep the history clean. In addition, we try to make our commits atomic and about one thing, rather than one feature set. That way, it makes it very helpful to remove a piece of code, cherry-pick a changeset to another branch, or find an offending commit that broke something.

So far, it's worked pretty well, but it might evolve as we go on.

Well, hope that helps. This post wasn't as fun to write, but it was something I hadn't see too much of out on the web, so I figured I'd contribute. Fun times.

Friday, January 23, 2009

Git allows my workflow to be "stateless" (or more advanced features of git)

I've been using git since May, and I feel like I use it pretty comfortably now. Oddly enough, with SVN, I just learned the basic check in and out, and left it at that. With git, I find that I want to do something--after poking around docs and tutorials, I find some of the advanced features of git something that I'd want to use.

Git has a bit of a learning curve, since their commands aren't exactly intuitive (deleting a remote repository anyone?, how about reverting is different from resetting?) you have to discard your notions of Svn, and learn how Git models a repository. But once you grasp that, it's pretty easy, not to mention pretty powerful. For me, Git had certain features that gave me a "wow", as I learned about and got use to using them. Here's in order as I discovered them.

Local branching


Branching is fast, and merging is relatively painless. When branching is fast, you end up treating branches are like tabs on your browser, but for source control. This lets you experiment with different code without affecting the main branch.

git checkout -b new_branch

Builtin Grep


I hated that grep would also search through the .svn files. Sure, I wrote an alias and script so that it wouldn't, but it would leak sometimes. Having git have a built-in grep was very nice.

git grep "some_regex"

Interactive staging of commits


Git has this idea of staging files, meaning marking them for a commit. Because you can commit different files, you can fix little things that might not have to do with your current ticket, but add them as separate commits.

But what if you edited one file but the edits had to do with two different tickets? With git, you can selectively stage parts of a file for committing.

git add -p

Rebasing branches


Rebase was a little confusing to me at first. The name didn't tell me anything. Rebase isa tool with multiple functions, with the same underlying principle, which is why it has just one name.

At the very basic, you can use rebase to move the root of the local branch if you want the changes made on the parent branch since then. This is important because it puts the burden of merging on the patch writer, and not on the merger. In addition, it makes for a cleaner commit history.

git checkout child_branch
git rebase parent_branch

Even better, you can reorder the commits as long as you haven't pushed it to a remote repository yet. The same task allows you to squash your commits together for a cleaner history.

git rebase -i HEAD~n

Stashing changes


Because you can stage files for commits and you can readily switch between branches, sometimes, you might be working on something, but they're not ready to be committed. The production code has a bug that needs to be fixed immediately. Git won't let you switch branches, but you don't want to commit unfinished code. What do you do?

Git lets you stash your changes to save your uncommitted changes, but not commit them anywhere. This is useful to switch to another branch to fix an emergency bug or perform other operations that require no uncommitted changes in the working directory (like rebase).

git stash
...fix bug on other branch...
git stash list
git stash apply

Bisection of commits


Sometimes, you're humming along with your commits, and you find that there was a part of the application that is broken, but your tests didn't catch it. You need to revert back to that version and make a branch. You can use git bisect to look for a particular commit. You give it a commit, and git will checkout that version, and ask you whether it works or not. Then it bisects the commits and half and then checks out the other half and asks you if it's correct. If not, it'll keep narrowing down the space of commits until you find the right one.

git bisect commit_hash other_commit_hash

Basically, a lot of what Git enables me to do is switch between tasks easily. I don't know if it's the right word, but it lets me work statelessly. At no time does git not let me do something because of a particular part of my workflow that I'm in. Outside of a few commands like rebase and merge (which can be fixed with stash), the commands I can run in git doesn't depend on the previous commands I've run. Really, git is a tabbed browser for me.

My biggest complaint is probably that the names of the commands aren't intuitive because it goes against the usual mental model of what a repo does. The names are actually make a lot more sense only after you understand how git models a repository. So take a look at the git book, and learn what you can.

tip!

Monday, January 12, 2009

iPhone jailbreaking resources because search has failed me.

A couple weeks back, I jailbroke my iPhone, so I could finally join the rest of the techno literati while on a carrier besides AT&T. However, this is one of those popular topics that are fraught with websites that just have a ridiculous number of ads on them. Not only that, it's mostly blogs repeating each other, and you get 2nd, 3rd, or maybe 50th hand information. And a lot of them are un-informational--only trying to sell you iPhone jailbreaking services. Didn't know the difference between jailbreaking and unlocking, and could barely find the page.

Because google search fails in this regard, I will recount that Jailbreaking is when you break the iPhone free of the app store, and you can install software from other sources and app installers, like Cydia. Unlocking is making your phone work with any phone carrier.

Surprisingly, these links were hard to fine--of the actual iPhone Dev Team Portal and of their forum. Those are what I found to be most helpful, though they don't even have a download page, which makes me kinda mad as I hunted around for it. Checkout yellowsn0w, as well as their QuickPwn, also here (much better than Z-phone). If you're still confused, which rightfully, you are. Over at iClarified, there are very good and clear tutorials on how to use the applications.

IPhone unlocking is one of those searches that I think Google just fails at. I hadn't noticed because most of what I search for is usually academic, mathematic, or open source developer related. Those two have been rather blissfully free of intrusive ads of non-informational webpages. With such a system, people know they're being watched and indexed, and if it's an advantage to get a 'high score', they're going to try to game (or optimize) on it. It seems uncannily related to sexual selection. I'll talk about that in another post in the future. For now, enjoy the iPhone resources