diff --git a/PGBuild/SCM.pm b/PGBuild/SCM.pm
index 16f5e85..275dbc2 100644
--- a/PGBuild/SCM.pm
+++ b/PGBuild/SCM.pm
@@ -1,6 +1,7 @@
 use strict;
 
 use File::Find;
+use File::Basename;
 
 =comment
 
@@ -454,6 +455,8 @@ sub new
         : abs_path("$conf->{build_root}") . "/$target-mirror.git"
     )if $conf->{git_keep_mirror};
     $self->{ignore_mirror_failure} = $conf->{git_ignore_mirror_failure};
+    $self->{use_workdirs} = $conf->{git_use_workdirs};
+    $self->{build_root} = $conf->{build_root};
     $self->{target} = $target;
     return bless $self, $class;
 }
@@ -572,6 +575,78 @@ sub checkout
         push(@gitlog,@pulllog);
         chdir '..';
     }
+    elsif ($branch ne 'HEAD' && $self->{use_workdirs} &&
+		   ! defined($self->{reference}) && $^O ne "MSWin32")
+    {
+
+		# exclude Windows for now - need to make sure how to do symlinks portably there
+		# early versions don't have mklink
+
+		# not sure how this plays with --reference, so for now I'm excluding that, too
+		# currently the following 4 members use --reference:
+		#     castoroides protosciurus mastodon narwhal
+
+        my $head = 	$self->{build_root} . '/HEAD';
+        unless (-d "$head/$target/.git")
+        {
+            # clone HEAD even if not (yet) needed for a run, as it will be the
+            # non-symlinked repo linkd to by all the others.
+
+            my $base = $self->{mirror} || $gitserver;
+
+            my $char1 = substr($base,0,1);
+            $base = "$drive$base"
+              if ( $char1 eq '/' or $char1 eq '\\');
+
+            mkdir $head;
+
+            my @clonelog = `git clone -q $base "$head/$target" 2>&1`;
+            push(@gitlog,@clonelog);
+            $status = $? >>8;
+            if (!$status)
+            {
+                my $savedir = getcwd();
+                chdir "$head/$target";
+
+                # make sure we don't name the new branch HEAD
+                my @colog =`git checkout -b bf_HEAD --track origin/master 2>&1`;
+                push(@gitlog,@colog);
+                chdir $savedir;
+            }
+        }
+
+        # now we can set up the git dir symlinks like git-new-workdir does
+
+        mkdir $target;
+        chdir $target;
+        mkdir ".git";
+        mkdir ".git/logs";
+        my @links =
+          qw (config refs logs/refs objects info hooks packed-refs remotes rr-cache svn);
+        foreach my $link (@links)
+        {
+            system(qq{ln -s "$head/$target/.git/$link" ".git/$link"});
+        }
+        copy("$head/$target/.git/HEAD", ".git/HEAD");
+
+		my @branches = `git branch`;
+		chomp @branches;
+		my @colog;
+		if (grep {/\bbf_$branch\b/ } @branches)
+		{
+			# don't try to create an existing branch
+			# the target dir only might have been wiped away,
+			# so we need to handle this case
+			@colog =`git checkout -f bf_$branch 2>&1`;
+		}
+		else
+		{
+			@colog =`git checkout -f -b bf_$branch --track origin/$branch 2>&1`;
+		}
+        push(@gitlog,@colog);
+
+        chdir "..";
+    }
     else
     {
         my $reference =
diff --git a/build-farm.conf b/build-farm.conf
index 0221c5d..56f313f 100644
--- a/build-farm.conf
+++ b/build-farm.conf
@@ -36,6 +36,10 @@ my $branch;
     git_keep_mirror => 1,  # manage a git mirror in the build root
     git_ignore_mirror_failure => 1, # ignore failures in fetching to mirror
 
+    # use symlinked git repo from non-HEAD branches,
+    # like git-new-workdir does
+    git_use_workdirs => 1,
+
     scmrepo => undef, # default is community repo for either type
     scm_url => undef, # webref for diffs on server - use default for community
     # git_reference => undef, # for --reference on git repo
