{"thread":{"id":"60584","subject":"git switch has fatal dependency on default fetch config","startedAt":"2023-12-06T03:41:30Z","lastAt":"2023-12-07T02:20:05Z","messageCount":3,"participants":["Jeremiah Steele (Jerry)","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"485360","messageId":"634F40AF-25F8-4FE6-BDE3-08798E699A9E@dubsado.com","threadId":"60584","inReplyTo":null,"subject":"git switch has fatal dependency on default fetch config","fromName":"Jeremiah Steele (Jerry)","fromEmail":"jeremiah@dubsado.com","sentAt":"2023-12-06T03:41:28Z","receivedAt":"2023-12-06T03:41:30Z","isPatch":false,"sender":{"key":"jeremiah@dubsado.com","avatar":null},"body":"Changing the default fetch refspec for a remote breaks git switch:\n\n% git branch -r\n  origin/HEAD -> origin/master\n  origin/feature\n  origin/master\n% git remote set-branches origin master\n% git switch -c feature --track origin/feature\nfatal: cannot set up tracking information; starting point 'origin/feature' is not a branch\n% git remote set-branches --add origin feature\n% git switch -c feature --track origin/feature\nbranch 'feature' set up to track 'origin/feature'.\nSwitched to a new branch 'feature'\n\nIt 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?"},{"id":"485389","messageId":"20231206191148.GA103708@coredump.intra.peff.net","threadId":"60584","inReplyTo":"634F40AF-25F8-4FE6-BDE3-08798E699A9E@dubsado.com","subject":"Re: git switch has fatal dependency on default fetch config","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2023-12-06T19:11:48Z","receivedAt":"2023-12-06T19:11:50Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Dec 05, 2023 at 07:41:28PM -0800, Jeremiah Steele (Jerry) wrote:\n\n> Changing the default fetch refspec for a remote breaks git switch:\n> \n> % git branch -r\n>   origin/HEAD -> origin/master\n>   origin/feature\n>   origin/master\n> % git remote set-branches origin master\n> % git switch -c feature --track origin/feature\n> fatal: cannot set up tracking information; starting point 'origin/feature' is not a branch\n> % git remote set-branches --add origin feature\n> % git switch -c feature --track origin/feature\n> branch 'feature' set up to track 'origin/feature'.\n> Switched to a new branch 'feature'\n> \n> It seems like I should be able to fetch a remote branch and track it\n> without having to monkey around with my default fetch config. Is there\n> a reason git switch has a hard dependency on the default remote fetch\n> refspec configuration?\n\nI think it's required by the form of the tracking config, which is\ndefined by a named remote and a remote branch, like:\n\n  [branch \"foo\"]\n  remote = origin\n  merge = refs/heads/foo\n\nYou explicitly asked to track \"origin/feature\", which means that Git has\nto be able to turn that into config as above. It can handle two cases:\n\n  1. It's a local branch in refs/heads/, in which case the remote is \".\"\n     and the \"merge\" field is the name of the branch.\n\n  2. It's a ref that can be found by reversing a fetch refspec. With the\n     default remote.origin.fetch refspec of refs/heads/*:refs/remotes/origin/*,\n     we know that \"refs/remotes/origin/feature\" comes from \"refs/heads/feature\"\n     on the \"origin\" remote.\n\n     But since you used \"remote set-branches\" to limit that refspec, we\n     can't do that same reversal. And \"origin/feature\", while we do\n     still have it as a ref, does not correspond to any remote ref we'd\n     fetch. So we don't know how to set up the tracking config.\n\nThe notion of \"tracking\" really came about as defining what \"git pull\"\ndoes. And without a remote that fetches, \"git pull\" does not really make\nmuch sense.\n\nI'd guess that you are more interested in being able to just use\n@{upstream}, especially as the default for things like rebase, etc. And\nthat could work without being able to actually fetch the ref. But those\ntwo things are intertwined in Git. You obviously can still base a branch\noff of \"origin/feature\", but you'll have to specify it manually when\ndoing rebase, etc.\n\n-Peff\n"},{"id":"485405","messageId":"94F78A2F-8AAA-49FE-A0A0-D63F1DAE3D31@dubsado.com","threadId":"60584","inReplyTo":"20231206191148.GA103708@coredump.intra.peff.net","subject":"Re: git switch has fatal dependency on default fetch config","fromName":"Jeremiah Steele (Jerry)","fromEmail":"jeremiah@dubsado.com","sentAt":"2023-12-07T02:20:02Z","receivedAt":"2023-12-07T02:20:05Z","isPatch":false,"sender":{"key":"jeremiah@dubsado.com","avatar":null},"body":"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.)\n\nThe 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:\n\n% git fetch origin feature # should fetch to refs/remotes/origin/feature\n% git switch feature # should find origin/feature, create a local branch with the same name, and set up tracking\n\nOh well.\n\nThanks for the response and the explanation.\n\n> On Dec 6, 2023, at 11:11 AM, Jeff King <peff@peff.net> wrote:\n> \n> On Tue, Dec 05, 2023 at 07:41:28PM -0800, Jeremiah Steele (Jerry) wrote:\n> \n>> Changing the default fetch refspec for a remote breaks git switch:\n>> \n>> % git branch -r\n>>  origin/HEAD -> origin/master\n>>  origin/feature\n>>  origin/master\n>> % git remote set-branches origin master\n>> % git switch -c feature --track origin/feature\n>> fatal: cannot set up tracking information; starting point 'origin/feature' is not a branch\n>> % git remote set-branches --add origin feature\n>> % git switch -c feature --track origin/feature\n>> branch 'feature' set up to track 'origin/feature'.\n>> Switched to a new branch 'feature'\n>> \n>> It seems like I should be able to fetch a remote branch and track it\n>> without having to monkey around with my default fetch config. Is there\n>> a reason git switch has a hard dependency on the default remote fetch\n>> refspec configuration?\n> \n> I think it's required by the form of the tracking config, which is\n> defined by a named remote and a remote branch, like:\n> \n>  [branch \"foo\"]\n>  remote = origin\n>  merge = refs/heads/foo\n> \n> You explicitly asked to track \"origin/feature\", which means that Git has\n> to be able to turn that into config as above. It can handle two cases:\n> \n>  1. It's a local branch in refs/heads/, in which case the remote is \".\"\n>     and the \"merge\" field is the name of the branch.\n> \n>  2. It's a ref that can be found by reversing a fetch refspec. With the\n>     default remote.origin.fetch refspec of refs/heads/*:refs/remotes/origin/*,\n>     we know that \"refs/remotes/origin/feature\" comes from \"refs/heads/feature\"\n>     on the \"origin\" remote.\n> \n>     But since you used \"remote set-branches\" to limit that refspec, we\n>     can't do that same reversal. And \"origin/feature\", while we do\n>     still have it as a ref, does not correspond to any remote ref we'd\n>     fetch. So we don't know how to set up the tracking config.\n> \n> The notion of \"tracking\" really came about as defining what \"git pull\"\n> does. And without a remote that fetches, \"git pull\" does not really make\n> much sense.\n> \n> I'd guess that you are more interested in being able to just use\n> @{upstream}, especially as the default for things like rebase, etc. And\n> that could work without being able to actually fetch the ref. But those\n> two things are intertwined in Git. You obviously can still base a branch\n> off of \"origin/feature\", but you'll have to specify it manually when\n> doing rebase, etc.\n> \n> -Peff\n\n"}]}