Mark Needham

Thoughts on Software Development

Archive for the ‘Version Control’ Category

Mercurial: hg bisect

with 3 comments

We've been using Mercurial locally on the project I've been working on and Phil showed me a cool feature called 'bisect' a couple of weeks ago which can be helpful for working out which revision we managed to break our code in.

It's been ported across from Git and is included in Mercurial from version 1.0.0 rather than just being an extension.

From the bisect extension page:

Its behaviour is fairly simple: it takes a first revision known to be correct (i.e. without the bug) and a last revision known to be bad (i.e. with the bug). The bisect extension ouputs a revision halfway between the good and the bad ones and lets you test it. If this revision is a good one, you mark it as good with hg bisect good, otherwise you mark it as bad with hg bisect bad. In both cases, bisect outputs a new revision to test, halfway between the good and the bad ones. You repeat until only one revision is left: the culprit.

The usage has changed a bit now that it's included as part of the initial download.

I was working on something yesterday and checking in fairly regularly before realising that I'd broken something.

I was fairly sure that the break had happened in the tip (revision 98) but I could only remember it definitely working in revision 96.

I defined the good and bad revisions like this:

hg bisect -b tip
hg bisect -g 96

In this case revision 97 was now checked out and I checked that the code was working with that revision before marking it:

hg bisect -g

It's now able to work out that the problem is in fact in revision 98:

The first bad revision is:
changeset:   98:86260809c309
tag:         tip
user:        mneedham
date:        Fri Nov 13 16:31:02 2009 +1100
summary:     seem to have screwed up the graphs. Not sure how

I managed to mess up setting up the good and bad revisions a few times – I somehow had the impression that I needed to manually update to the original good and bad revisions which isn't the case.

The reset command was my friend before I worked out what I was doing wrong:

hg bisect -r

It seems like a neat little feature. I'm sure there are lots of other cool things like this in Mercurial so if you know any let me know!

* Update *
As Rob points out in the comments the command is 'bisect' rather than 'bisec' as I had it originally. Both commands work for the moment though!

Written by Mark Needham

November 14th, 2009 at 11:20 am

Posted in Version Control

Tagged with , ,

Pulling from github on Windows

with one comment

My colleague Dave Cameron has been telling me about his adventures playing around with Git Sharp (a C# port of the Java Git implementation jGit) so I thought I'd get a copy of the code and have a look as well.

I tend to check out all code bases from my host machine instead of virtual machine so I got the code all checked out on the Mac and accessed it via a shared folder on my VM.

The problem with doing this is I was unable to run the tests due to the following error which I received repeatedly:

System.Security.SecurityException: That assembly does not allow partially trusted callers.
at GitSharp.Tests.ObjectCheckerTests.testInvalidCommitNoTree2()

I'm not sure exactly why I got this error but it's probably due to the fact that I didn't open the project in normal mode since I am accessing it on a shared drive.

I decided it would probably just be quicker to checkout the code directly from the VM instead.

I installed msysgit which all worked fine and then I went to clone my repository:

C:\Playbox>git clone git@github.com:mneedham/GitSharp.git

Which resulted in the following error:

Initialized empty Git repository in C:/Playbox/GitSharp/.git/
Permission denied (publickey).
fatal: The remote end hung up unexpectedly

I had the public key setup on my github account from when I was using Git from my Mac but I hadn't setup the private key that it requires inside my VM!

Browsing through the instructions on the github website I realised that I needed to copy my private key into the '.ssh' folder (which as I understand is the default folder for ssh settings to be stored).

This folder needs to be at the root of your user folder rather than at the root of the drive as I originally thought.

Therefore it should be at 'C:/Documents and Settings/Administrator/.ssh' for example rather than 'C:/.ssh' as I mistakenly had it.

I couldn't find a way to create a folder which started with a '.' from Windows explorer so I just created a folder called 'ssh' and then renamed it using 'mv ssh .ssh' from the command line.

I then copied my private key (which I got from the Mac by running 'less ~/.ssh/id_rsa') into a file called 'id_rsa' inside the '.ssh' folder and all was good:

C:\Playbox>git clone git@github.com:mneedham/GitSharp.git
Initialized empty Git repository in C:/Playbox/GitSharp/.git/
Enter passphrase for key '/c/Documents and Settings/Administrator/.ssh/id_rsa':
remote: Counting objects: 3138, done.
remote: Compressing objects: 100% (880/880), done.
remote: Total 3138 (delta 2319), reused 3039 (delta 2220)
Receiving objects: 100% (3138/3138), 3.72 MiB | 191 KiB/s, done.
Resolving deltas: 100% (2319/2319), done.
Checking out files: 100% (505/505), done.

In the process of working out what I'd done wrong I came across a nice post by Sergio Pereira which describes the whole process of getting up and running with Git in more detail.

Written by Mark Needham

August 18th, 2009 at 12:33 am

Posted in Version Control

Tagged with ,

Mercurial: Pulling from behind a proxy

with 5 comments

I've been playing around with Mercurial and the mercurial hosting website bitbucket a bit this year and recently wanted to pull from a repository from behind a proxy server.

With a bit of help from the mercurial mailing list and the documentation this is how I was able to pull the repository for the Hambread project I've been doing a bit of work on:

hg --config http_proxy.host=ipOfYourProxyServer:portOfYourProxyServer --config http_proxy.user=user --config http_proxy.passwd=password pull http://bitbucket.org/markhneedham/hambread

After that command a 'hg update' updates your local repository with all the changes that have just been pulled.

What I found strange was that you needed to define the '– config' part of the command three times as far as I can tell in order to pass each of the different properties related to the proxy.

I tried just defining it once and just setting the properties individually but that just produced errors.

Written by Mark Needham

May 13th, 2009 at 7:49 am

Posted in Version Control

Tagged with ,

Ignore file in Svn

with 2 comments

I spent a bit of time this afternoon marveling at the non intuitiveness of working out how to ignore files in Svn.

Normally I'd just use Tortoise SVN as it makes it so easy for you but I really wanted to know how to do it from the shell!

After a bit of Googling and conversation with a colleague I think I have it figured out to some extent.

Ignoring just one file or pattern

If you only have one pattern or file that you want to ignore then the following command should do the trick.

svn propset svn:ignore <file_or_pattern_to_ignore> <dir_in_which_to_create_ignore_file>

For example:

svn propset svn:ignore build .

This means my 'build' directory will now be ignored and the svn ignore file will be placed in the current directory.

Ignoring multiple files or patterns

The problem with the above approach comes when you want to ignore more than one pattern/file. If you just run the propset command again it overrides the current svn ignore file with the current value – clearly not what we want!

Luckily propedit comes to the rescue.

Running the following command will open up your chosen editor and allow you to edit the svn ignore file.

svn propedit svn:ignore <dir_where_ignore_file_resides>

When I initially did this I received the following error:

svn: None of the environment variables SVN_EDITOR, VISUAL or EDITOR is set, and no 'editor-cmd' run-time configuration option was found

I wanted my default editor to be Textmate so I entered the following:

export SVN_EDITOR=mate

This didn't seem to work for me – the svn tmp file being opened up in Textmate was always empty for some reason. Changing my editor to vi seemed to fix the problem.

export SVN_EDITOR=vi

Running the command now opens up vi and allowed me to add the pattern '*.log' to my ignore list. If it is added successfully the following message will show up on exiting vi:

Set new value for property 'svn:ignore' on '.'

Seeing which files or patterns are currently ignored

While having my Textmate problems detailed above my colleague pointed out the propget command which shows you which files/patterns are currently being ignored.

svn propget svn:ignore .

Running this command shows me the following:

build
*.log

svnbook has even more goodness on ignoring files for those that are interested.

Written by Mark Needham

October 2nd, 2008 at 9:10 pm

Posted in Version Control

Tagged with ,

Getting latest tagged revision in SVN from DOS/Batch script

with 2 comments

The way we have setup the build on our continuous integration server, Team City is configured to create a new tag every time the functional tests past successful on that machine.

We then have a QA and Showcase build that we can run to deploy all the artifacts necessary to launch the application on that machine.

Originally I had just written the batch script to take in the tag of the build which the user could find by looking through repo-browser for the last tag created. This quickly became very tedious so I started looking for a way to get the latest tagged revision from the command line.

We thought it would be possible to get this information using svn info but it turned out that the information returned by svn info about revisions doesn't necessarily refer to the latest created tag. We ended up using svn log and then parsing through that data. It's a bit messy but it does the job (I name each tagged version of the code as 'build-{TeamCity-Build-Number}):

1
2
FOR /F "Tokens=2" %%i in ('svn log /tags/path --limit=1 -v ^| find "build"') do set TMP=%%i
FOR /F "Tokens=2 delims=/" %%i in ('echo %TMP%') do SET TAG=%%i

The for loop uses a space as its default delimiter so that's what the 'delims=/' is doing on the second line, the 'Tokens=2′ allows us to get the second token after the string is split and the '^' in the first command is being used to escape the pipe.

Written by Mark Needham

August 16th, 2008 at 12:10 am