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
origin
branch 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 tracksorigin
'srelease-branch.go1.8
branch.If you already have a
release-branch.go1.8
branch (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
branch:
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'srelease-branch.go1.8
branch, even though it has the same URL as our regularorigin
remote (which will normally fetch all branches). - Edit
.git/config
to change thefetch =
line fororigin-v1.8
to fetch the branch intorefs/remotes/origin/release-branch.go1.8
, which is the fetch destination for yourorigin
remote. That is:fetch = +refs/heads/release-branch.go1.8:refs/remotes/origin/release-branch.go1.8
By fetching into
refs/remotes/origin
like 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 config
but I'd rather edit.git/config
by hand.) - Edit
.git/config
again to change the 'remote =
' line for yourrelease-branch.go1.8
branch to beorigin-v1.8
instead oforigin
.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 origin/release-branch.go1.8
.
In the master repo, it will (normally) report an attempt to update
everything.
Because everything is attached to our branch configuration for the
(local) 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
updating 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 origin
remote:
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.)
|
|