Archive

Archive for September, 2008

git-svn gotcha

September 29th, 2008
I was having problems with the following setup the other day:

 [remote deveoper] <===>; [shared git repo] <===> [me] <===> [client's svn repo]

So my remote developer and I push and pull to/from the shared git
repo, and then I sync changes to and from the client's svn repo using
git-svn.

Problem

My problem is, when I am ready to merge changes from my local master
branch to trunk-local, if I do a "git merge master" and then try to
issue any git-svn commands I get the following errors:

======================
$ git merge master
Updating d88106e..77b86ae
Fast forward
 community/pom.xml |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

$ git svn dcommit
Can't call method "full_url" on an undefined value at
/usr/local/git/libexec/git-core/git-svn line 425.

$ git svn rebase
Unable to determine upstream SVN information from working tree history
======================

The only way I've seem to be able to remedy this is if I add the
"subtree" merge strategy to the merge command:

git merge -s subtree master

Then git-svn doesn't get confused about it's repo, but when you look
at the repo using gitk, you see something like:

[trunk-local]--[remotes/trunk]  Merge branch 'master' into trunk-local
|
|
|    [master]--[remotes/origin/master]  "last master commit msg"
|    |
|    |
|  /
/

When I use the normal merge strategy then gitk shows all branches at
the same level, but git-svn is of course b0rked.

Solution

I tried asking a few people on #git (freenode irc channel for git) for help, but the problem was a bit too involved to explain on irc and have someon follow along, so instead what I did was I asked on the official git mailing list (git@vger.kernel.org) and I got an answer almost immediately from Björn Steinbrink with a solution that seems to work just great! His input was to use --no-ff when merging my changes into the svn tracking branch (trunk-local). Here is his explanation:

The original merge you did ended up as a fast-forward, ie. no merge
commit was created. I guess that your history is so, that somehow the
remotes/trunk stuff is reachable through the second parent of some merge
commit that exists in your history. But git-svn uses --first-parent to
find its upstream, so it cannot find that in your scenario. I guess it's
best if you use "*git merge --no-ff master*" to force the creation of a
merge commit. Subtree happens to work because it implies --no-ff, but
I'm not sure whether there might be downsides to using the subtree
strategy, so I'd rather go with the explicit --no-ff and the normal
merge strategies.

Hopes this helps other's in the same situation as I was in. Thanks Björn Steinbrink

General

Tip: mimic user file permissions to group

September 20th, 2008
I ran into a situation the other day where I had setup a git repository for myself and wanted to grant read/write access to another fellow who is helping out on the project. He could pull from the repository just fine, but couldn't push to it because the directory permissions on the repo were only setup for me to write to.

After creating a new group for us, adding our user ids to it and then doing a recursive chgrp on the repo I realized that by default git repositories are not setup for group writes unless you explicitly specify that at the time of creations (i.e. git init --shared=group. So I really needed a way to recursively mirror the user's file permissions on all files and directories in the repo to that of the group.

Searching long and hard I could not find a canned solution to this, perhaps one exists out there but because "mimic user file permissions to group" and "mirror user file permissions to group" don't yield good results in google, I was forced to write my own Perl script:

#!/usr/bin/perl
use File::stat;
use Fcntl ':mode';

foreach (@ARGV) {
    next unless -e $_;
    $stats = stat($_);
    $mode = substr(sprintf("%04o", $stats->mode), -3);
    $out = "$_ from $mode to ";
    $mode =~ s/(\d)(\d)(\d)/$1$1$3/;
    $out = "$out $mode";
    printf($out . "\n");
    chmod oct($mode), $_;
}

The Usage on this script is:

mimicuserperms.pl 

To use it recursively:

find . -exec mimicuserperms.pl {} \;

DISCLAIMER: Not sure if this will work on every single system out there, I mean it literally just grabs the last three file perms found by stat and takes the first character and duplicates it over the second. So use at your own risk! Perhaps, backup whatever you are going to use this on first before trying.

General

git gotcha

September 10th, 2008
Just thought I'd post about a problem I was having with git concerning the setup and cloning of a remote repository. Basically, if you've setup a repository on a remote machine, and want to clone from that machine onto a local one using ssh, you may run into problems like I did.

The error I received was:

ThaDonMBP:workspace craiger$ git clone craiger@192.168.2.10:/git/myproj
Initialized empty Git repository in /private/workspace/myproj/.git
craiger@192.168.2.10's password:
bash: git-upload-pack: command not found
fatal: The remote end hung up unexpectedly

The problem is that git is expecting git-upload-pack in a specific directory on the remote machine, and that is /usr/bin or /usr/local/bin. That's *not* where I had git installed, I had it installed in /opt/git/bin. So all you need to do is symlink your git executables to /usr/bin like so:

craiger@192.168.2.10:~$ cd /usr/bin
craiger@192.168.2.10:/usr/bin$ sudo ln -s /opt/git/bin/* .

After that, things should work!

General

Wicket in Action Review

September 9th, 2008
Wrote a review on the most excellent book Wicket in Action for the Mystic Coders.

For those who haven't heard of Wicket, it's a Java web framework that allows designers (the chaps good with Dreamweaver) to collaborate with the Developers (the guys good with Java) in such a way that neither destroys the others work. It's quite a great framework I encourage you to give it a try, and of course read the book!

General

Support Wikipedia