Archive for the ‘git’ tag
git: Only pushing some changes from local repository
Something that we want to do reasonable frequently on my current project is to push some changes which have been committed to our local repository to master but not all of them.
For example we might end up with 3 changes we haven’t pushed:
>> ~/github/local$ git status # On branch master # Your branch is ahead of 'origin/master' by 3 commits. # nothing to commit (working directory clean)
>> ~/github/local$ git hist * bb7b139 Thu, 20 Oct 2011 07:37:11 +0100 | mark: one last time (HEAD, master) [Mark Needham] * 1cef99a Thu, 20 Oct 2011 07:36:35 +0100 | mark:another new line [Mark Needham] * 850e105 Thu, 20 Oct 2011 07:36:01 +0100 | mark: new line [Mark Needham] * 2b25622 Thu, 20 Oct 2011 07:32:43 +0100 | mark: adding file for first time (origin/master) [Mark Needham]
And we only want to push the commit with hash 850e105 for example.
The approach which my colleague Uday showed us is to first take a temporary branch of the current state.
>> ~/github/local$ git checkout -b temp-branch Switched to a new branch 'temp-branch'
Then immediately switch back to master and ‘get rid’ of the last two changes from there:
>> ~/github/local$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits.
>> ~/github/local$ git reset HEAD~2 --hard HEAD is now at 850e105 mark: new line
We can then push just that change:
>> ~/github/local$ git push Counting objects: 5, done. Writing objects: 100% (3/3), 257 bytes, done. Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. To /Users/mneedham/github/remote 2b25622..850e105 master -> master
And merge the temporary branch back in again so we’re back where we were before:
>> ~/github/local$ git merge temp-branch Updating 850e105..bb7b139 Fast-forward foo.txt | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
>> ~/github/local$ git hist * bb7b139 Thu, 20 Oct 2011 07:37:11 +0100 | mark: one last time (HEAD, temp-branch, master) [Mark Needham] * 1cef99a Thu, 20 Oct 2011 07:36:35 +0100 | mark:another new line [Mark Needham] * 850e105 Thu, 20 Oct 2011 07:36:01 +0100 | mark: new line (origin/master) [Mark Needham] * 2b25622 Thu, 20 Oct 2011 07:32:43 +0100 | mark: adding file for first time [Mark Needham]
>> ~/github/local$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # nothing to commit (working directory clean)
And finally we delete the temporary branch:
>> ~/github/local$ git branch -d temp-branch Deleted branch temp-branch (was bb7b139).
We can achieve the same thing without creating the branch and just cherry picking the commits back again after we’ve pushed our changes but this seems approach seems quicker.
Git: Getting the history of a deleted file
We recently wanted to get the Git history of a file which we knew existed but had now been deleted so we could find out what had happened to it.
Using a simple git log didn’t work:
git log deletedFile.txt fatal: ambiguous argument 'deletedFile.txt': unknown revision or path not in the working tree.
We eventually came across Francois Marier’s blog post which points out that you need to use the following command instead:
git log -- deletedFile.txt
I’ve tried reading through the man page but I’m still not entirely sure what the distinction between using – and not using it is supposed to be.
If someone could explain it that’d be cool…
Git: Deleting a remote branch on a gitolite configured repository
We’ve had an xsbt branch on our gitolite powered repository for the last couple of weeks while we worked out how to move our build from sbt 0.7 to sbt 0.10 but having finally done that we needed to delete it.
I originally tried running the following command from one of our developer workstations:
git push origin :xsbt
But ended up with the following error:
remote: error: denying ref deletion for regs/head/xsbt
! [remote rejected] xsbt (deletion prohibited)
A bit of googling led me to this stackoverflow thread which suggested that you needed to be an administrator in order to delete a remote branch.
Once we’ve done that we can run the following command on each machine to delete the remote tracking reference to the repository:
git branch -d -r origin/xsbt
Git/Mercurial: Pushing regularly
I was reading a recent blog post by Gabriel Schenker where he discusses how his team is making use of Git and about half way through he says the following:
When using Git as your SCM it is normal to work for quite a while – maybe for a couple of days – in a local branch and without ever pushing the changes to the origin. Usually we only push when a feature is done or a defect is completely resolved.
We’ve been using Mercurial on the project I’m currently working on over the past few months and although it’s a similar tool we’ve been following a different approach.
We’ve got it setup the same way we would setup Subversion:

We’ve been trying to push to the central repository as frequently as possible, just as we would if we were using Subversion.
I don’t know the Git workflow that well because I haven’t used it on a project yet but we’ve always found that it’s beneficial to integrate with code being written by others on the team as frequently as possible.
Not doing this can lead to the problems which Martin Fowler outlines in his post about feature branches.
We’ve tried to ensure that after every commit the build still passes although we do sometimes have broken versions in the code committed locally because we don’t run our full test suite before every local check in.
Even if a feature isn’t completed I still think it’s valuable to have what we’ve done so far checked in and it also helps remove the problem with needing to backup local repositories:
Since we are going to work locally potentially for days without pushing to the origin (our central repository) we might well loose our work if we have a hard disk crash or our office is flooded. Thus we need some backup strategy.
We just need to make sure the central repository is being backed up and then the danger of losing our work is significantly reduced.
A reminder of the usefulness of Git
Despite the fact that none of the projects that I’ve worked on have used Git or Mercurial as the team’s main repository I keep forgetting how useful those tools can be even if they’re just being used locally.
I ran into a problem when trying to work out why a Rhino Mocks expectation wasn’t working as I expected last week having refactored a bit of code to include a constructor.
I wanted to include the Rhino Mocks source code in our solution before and after the refactoring and step through the code to see what was different in the way the expectations were being setup.
My initial thought was that I could just check out the repository again in another folder and then include the Rhino Mocks source code there and step through it but unfortunately we have all the projects set up to deploy to IIS so Visual Studio wanted me to adjust all those settings in order to load the solution in the new checkout location.
I probably could have gone and turned off that setting but it seemed a bit too much effort and I realised that I could easily use Git to help me solve the problem.
I took a patch of the changes I’d made and then reverted the code before checking it into a local Git repository.
I updated the solution to include the Rhino Mocks code and then created a branch called ‘refactoringChanges’ so that I could then apply the patch that I’d created with my changes.
It was then really easy to switch back between the two branches and see the differences in the way that the Rhino Mocks was working internally.
The actual problem eventually turned out to be the way that the code calls Castle DynamicProxy but I didn’t get the chance to look further into it – we had learnt enough to know how we could get around the problem.
I’m in the process of including the source code for all the 3rd party libraries that we use in the solution on a separate Git branch that I can switch to when I want to debug through that code.
Sometimes I end up having to close down Visual Studio and re-open the solution when I switch to and from that branch but apart from that it seems to work reasonably well so far.
Pulling from github on Windows
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.