For me, the main convenience of upstream tracking is for "git status" ahead/behind info, which requires you to have already fetched changes from the remote. For my "normal" work, I have a small set of branches set as default fetch refs. When I need to work on a branch not in that set, I fetch that specific branch. (I'm not interested in downloading and creating hundreds of branches when I only need one.) The requirement to reverse-engineer from the *default* fetch refspec seems like an odd implementation choice and a major shortcoming for storing tracking configuration. The vast majority of the time, origin/branch will map to refs/heads/branch on the remote anyhow. When I have a command that sets up tracking configuration, I would expect to be able to specify the remote refspec somehow, rather than having a hard dependency on a configuration value for default behavior. I feel like the following sequence should work as expected (with a limited default fetch spec), but there are several things that go wrong: % git fetch origin feature # should fetch to refs/remotes/origin/feature % git switch feature # should find origin/feature, create a local branch with the same name, and set up tracking Oh well. Thanks for the response and the explanation. > On Dec 6, 2023, at 11:11 AM, Jeff King <peff@xxxxxxxx> wrote: > > On Tue, Dec 05, 2023 at 07:41:28PM -0800, Jeremiah Steele (Jerry) wrote: > >> Changing the default fetch refspec for a remote breaks git switch: >> >> % git branch -r >> origin/HEAD -> origin/master >> origin/feature >> origin/master >> % git remote set-branches origin master >> % git switch -c feature --track origin/feature >> fatal: cannot set up tracking information; starting point 'origin/feature' is not a branch >> % git remote set-branches --add origin feature >> % git switch -c feature --track origin/feature >> branch 'feature' set up to track 'origin/feature'. >> Switched to a new branch 'feature' >> >> It seems like I should be able to fetch a remote branch and track it >> without having to monkey around with my default fetch config. Is there >> a reason git switch has a hard dependency on the default remote fetch >> refspec configuration? > > I think it's required by the form of the tracking config, which is > defined by a named remote and a remote branch, like: > > [branch "foo"] > remote = origin > merge = refs/heads/foo > > You explicitly asked to track "origin/feature", which means that Git has > to be able to turn that into config as above. It can handle two cases: > > 1. It's a local branch in refs/heads/, in which case the remote is "." > and the "merge" field is the name of the branch. > > 2. It's a ref that can be found by reversing a fetch refspec. With the > default remote.origin.fetch refspec of refs/heads/*:refs/remotes/origin/*, > we know that "refs/remotes/origin/feature" comes from "refs/heads/feature" > on the "origin" remote. > > But since you used "remote set-branches" to limit that refspec, we > can't do that same reversal. And "origin/feature", while we do > still have it as a ref, does not correspond to any remote ref we'd > fetch. So we don't know how to set up the tracking config. > > The notion of "tracking" really came about as defining what "git pull" > does. And without a remote that fetches, "git pull" does not really make > much sense. > > I'd guess that you are more interested in being able to just use > @{upstream}, especially as the default for things like rebase, etc. And > that could work without being able to actually fetch the ref. But those > two things are intertwined in Git. You obviously can still base a branch > off of "origin/feature", but you'll have to specify it manually when > doing rebase, etc. > > -Peff