Configuring Git worktrees to limit what's fetched on pulls
Yesterday I wrote about my practical problem with git worktrees, which is to limit what is fetched from the
remote when I do '
git pull' in one (as opposed to the main repo).
I also included a sidebar with a theory on how to do this with some
Git configuration madness. In a spirit of crazed experimentation
I've now put this theory into practice and it appears to actually
work. Unfortunately the way I know how to do this requires some
hand editing of your
.git/config, rather than using commands like
git remote' to do this for you. However, I don't fully understand
what I'm doing here (and that's one reason I'm putting in lots of
notes to myself).
Here's my process:
- Create a new worktree as normal, based from the
originbranch you want:
git worktree add -b release-branch.go1.8 ../v1.8 origin/release-branch.go1.8
Because we used
-b, this will also create a local remote-tracking branch,
release-branch.go1.8, that tracks
If you already have a
release-branch.go1.8branch (perhaps you've checked it out in your main repo at some point or previously created a worktree for it), this is just:
git worktree add ../v1.8 release-branch.go1.8
- Create a new remote for your upstream repo to fetch just this upstream
git remote add -t release-branch.go1.8 origin-v1.8 https://go.googlesource.com/go
Because we set it up to track only a specific remote branch, '
git fetch' for this remote will only fetch updates for the remote's
release-branch.go1.8branch, even though it has the same URL as our regular
originremote (which will normally fetch all branches).
.git/configto change the
fetch =line for
origin-v1.8to fetch the branch into
refs/remotes/origin/release-branch.go1.8, which is the fetch destination for your
originremote. That is:
fetch = +refs/heads/release-branch.go1.8:refs/remotes/origin/release-branch.go1.8
By fetching into
refs/remotes/originlike this, my understanding is that we avoid doing duplicate fetches. Whether we do '
git fetch' in our worktree or in the maste repo, we'll be updating the same remote branch reference and so we'll only fetch updates for this (remote) branch once. I believe that if you don't do this, '
git pull' or '
git fetch' in the worktree will always report the new updates; you'll never 'lose' an update for the branch by doing a '
git pull' in the master. However I think you may wind up doing extra transfers.
(This can be done with
git configbut I'd rather edit
.git/configagain to change the '
remote =' line for your
release-branch.go1.8branch to be
By forcing the remote for the branch, we activate
git fetch's restriction on what remote branches will be fetched when we do a '
git pull' or '
git fetch' in a tree with that branch checked out (here, our worktree, but it could be the master repo).
If you prefer, you can set this with '
git config' instead of by hand editing:
git config branch.release-branch.go1.8.remote origin-v1.8
We can see that this works by comparing '
git fetch -v --dry-run'
in the worktree and in the master repo. In the worktree, it will
report just an attempt to update
In the master repo, it will (normally) report an attempt to update
Because everything is attached to our branch configuration for the
release-branch.go1.8 branch, not the worktree, this will
survive removing and then re-recreating the worktree. This may be
a feature, or it may be a drawback, since it means that if you
delete the worktree and check out
release-branch.go1.8 in the
master repo, '
git pull' will start only updating it (and not
master and other branches as well). We can change back
to the normal state of things by updating the
remote for the
branch back to the normal
git config branch.release-branch.go1.8.remote origin
(In general you can flip the state of the branch back and forth as you want. I don't think Git gets confused, although you may.)