Thursday, 10 April 2008

Rails and git - clean branch and merge



I've moved over to git recently to take advantage of the new distributed functionality and the various git repository engines that are springing up in the Rails world.

One of the beauties of the new git regime is that creating and deleting test branches of your application is an absolute doddle. For every iteration you simply






neil@neil-laptop:~/test_git$ git checkout -b new_branch
Switched to a new branch "new_branch"
neil@neil-laptop:~/test_git$ *change something*
neil@neil-laptop:~/test_git$ git commit -a -m "let's try this"
Created commit cb3200f: let's try this
1 files changed, 0 insertions(+), 59 deletions(-)
neil@neil-laptop:~/test_git$ *add something else*
neil@neil-laptop:~/test_git$ git add .; git commit -a -m "That didn't work,
let's try something else"
Created commit 0c5f35e: That didn't work, let's try something else
1 files changed, 144 insertions(+), 0 deletions(-)
create mode 100644 FOOBAR
neil@neil-laptop:~/test_git$ *change something again*
neil@neil-laptop:~/test_git$ git commit -a -m "Now we've cracked it"
Created commit 3876936: Now we've cracked it
1 files changed, 0 insertions(+), 144 deletions(-)
delete mode 100644 FOOBAR
neil@neil-laptop:~/test_git$


Which gives you a nice branch with your shiny new functionality in it, but all the hacks and changes are in the log file.


neil@neil-laptop:~/test_git$ git-log --pretty=oneline master..HEAD
3876936d77f6963a5db461fbc013059c84a5e480 Now we've cracked it
0c5f35e7a0386698e57eab0791f5897cb44a0266 That didn't work, let's try something e
cb3200fd16de9bf4a14cbdba1a8abcfa0fcfeb71 let's try this


And that means when you merge down all those log entries get merged as well


neil@neil-laptop:~/test_git$ git checkout try_merge
Switched to branch "try_merge"
neil@neil-laptop:~/test_git$ git merge new_branch
Updating 1b63b7d..3876936

Fast forward
FRED | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
README | 59 --------------------------
2 files changed, 144 insertions(+), 59 deletions(-)
create mode 100644 FRED
neil@neil-laptop:~/test_git$ git branch -d new_branch
Deleted branch new_branch.
neil@neil-laptop:~/test_git$ git-log --pretty=oneline master..HEAD
3876936d77f6963a5db461fbc013059c84a5e480 Now we've cracked it
0c5f35e7a0386698e57eab0791f5897cb44a0266 That didn't work, let's try something
6182c9866e6f4972eb74e873f5d9eff1dd0a272d That didn't work try something else
cb3200fd16de9bf4a14cbdba1a8abcfa0fcfeb71 let's try this


Now recording your twists and turns for posterity probably isn't what you'd want to do. Fortunately there is an alternative. Let's do that again.


neil@neil-laptop:~/test_git$ git checkout try_merge
Switched to branch "try_merge"
neil@neil-laptop:~/test_git$ git-merge --squash new_branch
Updating 1b63b7d..766208c

Fast forward
Squash commit -- not updating HEAD
README | 31 -------------------------------
1 files changed, 0 insertions(+), 31 deletions(-)
neil@neil-laptop:~/test_git$ git commit -a -m 'Shiny new functionality as if by magic'
Created commit 2940a71: Shiny new functionality as if by magic
1 files changed, 0 insertions(+), 31 deletions(-)
neil@neil-laptop:~/test_git$ git-log --pretty=oneline master..
2940a71686d0c618bf39c17d3dd12c8ee02248d7 Shiny new functionality as if by magic
neil@neil-laptop:~/test_git$


Now all the twists and turns of your test branch are banished from history and you can pretend you created the perfect solution first time :-)

The one wrinkle is that you have to force delete the test branch. If you do a normal delete it complains

neil@neil-laptop:~/test_git$ git branch -d new_branch
error: The branch 'new_branch' is not a strict subset of your current HEAD.
If you are sure you want to delete it, run 'git branch -D new_branch'.

However if you take the advice all is well

neil@neil-laptop:~/test_git$ git branch -D new_branch
Deleted branch new_branch.

Git makes it really simple to launch a branch for every iteration you undertake and allows you to keep your mainline commit sequence clean.

No comments: