{"thread":{"id":"54755","subject":"Unexpected behavior with branch.*.{remote,pushremote,merge}","startedAt":"2020-12-04T01:27:39Z","lastAt":"2020-12-04T22:21:41Z","messageCount":9,"participants":["Ben Denhartog","Felipe Contreras","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"411290","messageId":"a4ae4e1a-b457-4b35-878c-2714ebfc415f@www.fastmail.com","threadId":"54755","inReplyTo":null,"subject":"Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Ben Denhartog","fromEmail":"ben@sudoforge.com","sentAt":"2020-12-04T01:26:15Z","receivedAt":"2020-12-04T01:27:39Z","isPatch":false,"sender":{"key":"ben@sudoforge.com","avatar":null},"body":"I have a few repositories on my system that exist primarily as local copies of remote repositories, in that I normally just want to track and follow the upstream project (however, I periodically contribute back upstream so they are technically forks -- origin is my remote, upstream is theirs).\n\nIn these repositories, I set the following configuration:\n\n```\n[remote \"origin\"]\n  url = https://git.foo.com/me/bar.git\n  fetch = +refs/heads/*:refs/remotes/origin/*\n[remote \"upstream\"]\n  url = https://git.foo.com/them/bar.git\n  fetch = +refs/heads/main:refs/remotes/upstream/main\n  tagopt = --no-tags\n[branch \"main\"]\n  remote = upstream\n  pushRemote = origin\n  merge = refs/heads/master\n  rebase = true\n```\n\nBased on my understanding of the branch configuration options, this should effectively force my local `main` branch to track against `upstream/main`, but push to `origin/main`. I notice what I believe to be odd behavior when fetching: that FETCH_HEAD doesn't resolve to `upstream/main` as I would expect:\n\n```\n➜ git fetch --all\nFetching origin\nFetching upstream\nremote: Enumerating objects: 23, done.\nremote: Counting objects: 100% (23/23), done.\nremote: Total 32 (delta 23), reused 23 (delta 23), pack-reused 9\nUnpacking objects: 100% (32/32), 12.97 KiB | 949.00 KiB/s, done.\nFrom https://git.foo.com/them/bar\n   63f7159..e65b80e  main     -> upstream/main\n\n\n➜ git status -sbu\n## main...upstream/main [behind 9]\n\n\n➜ git rev-parse HEAD upstream/main origin/main FETCH_HEAD\n63f71597979edb16cb9f80d0431115e22dcb716d\ne65b80edd2a2162f67120a98e84bb489f15fcf97\n23e6881719f661c37336d9fcf7a9005a7dfce0cf\n23e6881719f661c37336d9fcf7a9005a7dfce0cf\n```\n\nAs we see from the output, `FETCH_HEAD` is resolving to the same commit as `origin/main`, when I would instead expect it to resolve to the same commit as `upstream/main`. Here are the contents of `.git/FETCH_HEAD` in its entirety:\n\n```\n➜ cat .git/FETCH_HEAD\n23e6881719f661c37336d9fcf7a9005a7dfce0cf        not-for-merge   branch 'main' of https://git.foo.com/me/foo\ne65b80edd2a2162f67120a98e84bb489f15fcf97                branch 'main' of https://git.foo.com/them/foo\n```\n\nCuriously, `git rebase FETCH_HEAD` seems to think the local branch is up to date (erroneously), however `git-pull --rebase=true` and `git-merge FETCH_HEAD` both work as expected and merge/rebase with `upstream/main`.\n\nAm I going about this incorrectly? The main purpose behind configuring my \"mostly just a fork\" repository is that it simplifies tracking against an upstream remote for projects which I do not work on actively. Of course, you might argue that I don't need to keep my remote around for this purpose and can just use a straightforward `git-clone` here -- but I'd rather not, and would prefer responses addressing the perceived bug rather than suggesting this particular alternative workflow.\n\n-- \n  Ben Denhartog\n  ben@sudoforge.com\n"},{"id":"411292","messageId":"CAMP44s2=3GrXf69jqVJ23U=N9QcmGb-dHP_OEqyb6MVTY2z7Jg@mail.gmail.com","threadId":"54755","inReplyTo":"a4ae4e1a-b457-4b35-878c-2714ebfc415f@www.fastmail.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2020-12-04T02:31:06Z","receivedAt":"2020-12-04T02:32:21Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Thu, Dec 3, 2020 at 7:29 PM Ben Denhartog <ben@sudoforge.com> wrote:\n>\n> I have a few repositories on my system that exist primarily as local copies of remote repositories, in that I normally just want to track and follow the upstream project (however, I periodically contribute back upstream so they are technically forks -- origin is my remote, upstream is theirs).\n\nOtherwise known as a triangular workflow, for which in my opinion git\ndoesn't have good support.\n\nI wrote about it in my blog [1], and I wrote the patches to properly\nsupport that mode [2]. Unfortunately they were not merged.\n\nCheers.\n\n[1] https://felipec.wordpress.com/2014/05/11/git-triangular-workflows/\n[2] https://lore.kernel.org/git/1398023106-25958-1-git-send-email-felipe.contreras@gmail.com/\n\n-- \nFelipe Contreras\n"},{"id":"411319","messageId":"X8oL190Vl03B0cQ/@coredump.intra.peff.net","threadId":"54755","inReplyTo":"a4ae4e1a-b457-4b35-878c-2714ebfc415f@www.fastmail.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2020-12-04T10:13:43Z","receivedAt":"2020-12-04T10:14:42Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 03, 2020 at 06:26:15PM -0700, Ben Denhartog wrote:\n\n> I have a few repositories on my system that exist primarily as local copies of remote repositories, in that I normally just want to track and follow the upstream project (however, I periodically contribute back upstream so they are technically forks -- origin is my remote, upstream is theirs).\n> \n> In these repositories, I set the following configuration:\n> \n> ```\n> [remote \"origin\"]\n>   url = https://git.foo.com/me/bar.git\n>   fetch = +refs/heads/*:refs/remotes/origin/*\n> [remote \"upstream\"]\n>   url = https://git.foo.com/them/bar.git\n>   fetch = +refs/heads/main:refs/remotes/upstream/main\n>   tagopt = --no-tags\n> [branch \"main\"]\n>   remote = upstream\n>   pushRemote = origin\n>   merge = refs/heads/master\n>   rebase = true\n> ```\n\nI use a similar setup myself, and it works well for this kind of\ntriangular flow. A few notes:\n\n  - I assume you mean \"merge = refs/heads/main\" from your examples\n\n  - instead of branch.*.pushremote, I usually set remote.pushdefault, so\n    that it covers all branches (i.e., I'd never want to push to the\n    upstream remote, which I do not even have access to).\n\n  - in a workflow like this, I generally have push.default set to\n    \"current\"\n\n  - I make frequent use of @{push} to refer to the matching branch on my\n    remote (e.g., after doing some local work, I might use \"git\n    range-diff upstream @{push} HEAD\" to examine the changes before\n    pushing them up).\n\n> Based on my understanding of the branch configuration options, this\n> should effectively force my local `main` branch to track against\n> `upstream/main`, but push to `origin/main`. I notice what I believe to\n> be odd behavior when fetching: that FETCH_HEAD doesn't resolve to\n> `upstream/main` as I would expect:\n> \n> ➜ git fetch --all\n> Fetching origin\n> Fetching upstream\n> remote: Enumerating objects: 23, done.\n> remote: Counting objects: 100% (23/23), done.\n> remote: Total 32 (delta 23), reused 23 (delta 23), pack-reused 9\n> Unpacking objects: 100% (32/32), 12.97 KiB | 949.00 KiB/s, done.\n> From https://git.foo.com/them/bar\n>    63f7159..e65b80e  main     -> upstream/main\n\nThe culprit here is using \"git fetch --all\". It triggers the sub-fetches\nwith --append, so they'll each add to FETCH_HEAD instead of overwriting\nit.  We do truncate it before the first one, so after this completes it\nshould have the complete set of refs fetched from both remotes (even if\nit was a noop to fetch one of them, anything mentioned in the refspecs\nshows up in FETCH_HEAD).\n\nWhich is what you're seeing here:\n\n> ➜ cat .git/FETCH_HEAD\n> 23e6881719f661c37336d9fcf7a9005a7dfce0cf        not-for-merge   branch 'main' of https://git.foo.com/me/foo\n> e65b80edd2a2162f67120a98e84bb489f15fcf97                branch 'main' of https://git.foo.com/them/foo\n\nFETCH_HEAD is not just a ref, but contains some magic instructions that\nget interpreted by git-pull. But when programs besides git-pull try to\nresolve it to a single object, they just pick whichever value is first.\n\nSo I do think there's a bug there, or at least something not\nwell-thought-out in the way that \"fetch --all\" appends. Normally fetch\ntries to put the merge branch (or branches) first in the file, exactly\nso this naive \"take the first one\" lookup will do the most sensible\nthing. But when running multiple fetches that all append, we get their\nindividual outputs in the order of fetch (which in turn is the same as\nthe order in the config file).\n\nPerhaps the parent \"git fetch --all\" triggering the sub-fetches should\nreorder FETCH_HEAD after they've all finished (to pull any merge heads\nup to the top, regardless of which remote they came from).\n\nBut an obvious workaround, if you know you'll always be merging from\nupstream, is to just reorder your config stanzas so that it's fetched\nfirst (likewise you can run \"git fetch --multiple upstream origin\" to\nspecify the order manually, or define a group with remotes.<group>).\n\nOne reason I suspect nobody has come across this before is that there's\nnot much reason to use FETCH_HEAD in this setting. If you know you want\nto rebase again upstream/main, then there are a number of ways you can\nrefer to that:\n\n  - upstream/main\n\n  - upstream, if your refs/remotes/upstream/HEAD is set up (if you\n    didn't clone, you may want to run \"git remote set-head upstream -a\")\n\n  - @{upstream}, if it's configured as your upstream (which it is here)\n\n  - @{u}, a shorter synonym\n\n  - nothing at all, since rebasing against the upstream is the default\n    for git-rebase these days\n\n  - you can say that (or even just \"upstream\", if your\n    refs/remotes/origin/HEAD is set up)\n\n> Curiously, `git rebase FETCH_HEAD` seems to think the local branch is\n> up to date (erroneously),\n\nThat's what I'd expect, since it is doing the naive \"what is the first\none in the file\" lookup.\n\n> however `git-pull --rebase=true` [works]\n\nThat is running a new git-fetch under the hood, which will overwrite\nFETCH_HEAD (and will only fetch from upstream, since that's what's in\nbranch.main.remote).\n\n> `git-merge FETCH_HEAD` both work as expected and merge/rebase with\n> `upstream/main`.\n\nI think git-merge, like git-pull, understands the magic FETCH_HEAD\nformat.\n\n> Am I going about this incorrectly? The main purpose behind configuring\n> my \"mostly just a fork\" repository is that it simplifies tracking\n> against an upstream remote for projects which I do not work on\n> actively. Of course, you might argue that I don't need to keep my\n> remote around for this purpose and can just use a straightforward\n> `git-clone` here -- but I'd rather not, and would prefer responses\n> addressing the perceived bug rather than suggesting this particular\n> alternative workflow.\n\nI think your workflow is perfectly reasonable.\n\n-Peff\n"},{"id":"411334","messageId":"601563bf-ed54-4795-917a-fce6e9343b79@www.fastmail.com","threadId":"54755","inReplyTo":"CAMP44s2=3GrXf69jqVJ23U=N9QcmGb-dHP_OEqyb6MVTY2z7Jg@mail.gmail.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Ben Denhartog","fromEmail":"ben@sudoforge.com","sentAt":"2020-12-04T16:44:59Z","receivedAt":"2020-12-04T16:46:51Z","isPatch":false,"sender":{"key":"ben@sudoforge.com","avatar":null},"body":"I'm just now hearing the terminology \"triangular workflow\" (I may live under a rock), but that aptly and succintly describes the workflow I was attempting to simplify with my initial configuration.\n\nI read the article on your blog, and the solution you propose makes sense to me, at least in the context of triangular workflows. I don't see any public feedback on your patch; bummer to see. Is it something you've brought up since 2014?\n\n-- \n  Ben Denhartog\n  ben@sudoforge.com\n\nOn Thu, Dec 3, 2020, at 19:31, Felipe Contreras wrote:\n> On Thu, Dec 3, 2020 at 7:29 PM Ben Denhartog <ben@sudoforge.com> wrote:\n> >\n> > I have a few repositories on my system that exist primarily as local copies of remote repositories, in that I normally just want to track and follow the upstream project (however, I periodically contribute back upstream so they are technically forks -- origin is my remote, upstream is theirs).\n> \n> Otherwise known as a triangular workflow, for which in my opinion git\n> doesn't have good support.\n> \n> I wrote about it in my blog [1], and I wrote the patches to properly\n> support that mode [2]. Unfortunately they were not merged.\n> \n> Cheers.\n> \n> [1] https://felipec.wordpress.com/2014/05/11/git-triangular-workflows/\n> [2] \n> https://lore.kernel.org/git/1398023106-25958-1-git-send-email-felipe.contreras@gmail.com/\n> \n> -- \n> Felipe Contreras\n>\n"},{"id":"411335","messageId":"112958f6-0eca-453d-86f3-52e7054a88f9@www.fastmail.com","threadId":"54755","inReplyTo":"X8oL190Vl03B0cQ/@coredump.intra.peff.net","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Ben Denhartog","fromEmail":"ben@sudoforge.com","sentAt":"2020-12-04T16:45:17Z","receivedAt":"2020-12-04T16:46:51Z","isPatch":false,"sender":{"key":"ben@sudoforge.com","avatar":null},"body":"> I assume you mean \"merge = refs/heads/main\" from your examples\n\nYou're correct; I manually rewrote `master` to `main` in my initial email and missed that one instance.\n\n>   - instead of branch.*.pushremote, I usually set remote.pushdefault, so\n>     that it covers all branches (i.e., I'd never want to push to the\n>     upstream remote, which I do not even have access to).\n> \n>   - in a workflow like this, I generally have push.default set to\n>     \"current\"\n> \n>   - I make frequent use of @{push} to refer to the matching branch on my\n>     remote (e.g., after doing some local work, I might use \"git\n>     range-diff upstream @{push} HEAD\" to examine the changes before\n>     pushing them up).\n\nThis makes sense. I rarely actually write `FETCH_HEAD` manually; in my email, I expanded the value of aliases I use. Specifically, my \"get everything up-to-date\" alias [0] uses `FETCH_HEAD` -- changing this to `@{u}` makes a lot of sense.\n\n[0]: https://github.com/sudoforge/dotfiles/blob/trunk/git/.config/git/config#L104\n\n> > however `git-pull --rebase=true` [works]\n> \n> That is running a new git-fetch under the hood, which will overwrite\n> FETCH_HEAD (and will only fetch from upstream, since that's what's in\n> branch.main.remote).\n\nD'oh -- I wasn't focusing on the fact that this would only fetch the branch's configured remote; I blame it on tunnel vision.\n\nTo the rest of your message:\n\nI did not understand the behavior of `fetch --all`; what you've described makes sense to me (although I would agree that it sounds like there's a bug). Between the following steps I'll take, I think my fork workflow is \"fixed\":\n\n* Refactor away from usage of FETCH_HEAD\n* Set `remote.pushdefault = origin`\n* Set `push.default = current` (instead of `simple`, and is what my global config sets this to)\n\nI appreciate your insight and the identification of the problem.\n\n\n-- \n  Ben Denhartog\n  ben@sudoforge.com\n\nOn Fri, Dec 4, 2020, at 03:13, Jeff King wrote:\n> On Thu, Dec 03, 2020 at 06:26:15PM -0700, Ben Denhartog wrote:\n> \n> > I have a few repositories on my system that exist primarily as local copies of remote repositories, in that I normally just want to track and follow the upstream project (however, I periodically contribute back upstream so they are technically forks -- origin is my remote, upstream is theirs).\n> > \n> > In these repositories, I set the following configuration:\n> > \n> > ```\n> > [remote \"origin\"]\n> >   url = https://git.foo.com/me/bar.git\n> >   fetch = +refs/heads/*:refs/remotes/origin/*\n> > [remote \"upstream\"]\n> >   url = https://git.foo.com/them/bar.git\n> >   fetch = +refs/heads/main:refs/remotes/upstream/main\n> >   tagopt = --no-tags\n> > [branch \"main\"]\n> >   remote = upstream\n> >   pushRemote = origin\n> >   merge = refs/heads/master\n> >   rebase = true\n> > ```\n> \n> I use a similar setup myself, and it works well for this kind of\n> triangular flow. A few notes:\n> \n>   - I assume you mean \"merge = refs/heads/main\" from your examples\n> \n>   - instead of branch.*.pushremote, I usually set remote.pushdefault, so\n>     that it covers all branches (i.e., I'd never want to push to the\n>     upstream remote, which I do not even have access to).\n> \n>   - in a workflow like this, I generally have push.default set to\n>     \"current\"\n> \n>   - I make frequent use of @{push} to refer to the matching branch on my\n>     remote (e.g., after doing some local work, I might use \"git\n>     range-diff upstream @{push} HEAD\" to examine the changes before\n>     pushing them up).\n> \n> > Based on my understanding of the branch configuration options, this\n> > should effectively force my local `main` branch to track against\n> > `upstream/main`, but push to `origin/main`. I notice what I believe to\n> > be odd behavior when fetching: that FETCH_HEAD doesn't resolve to\n> > `upstream/main` as I would expect:\n> > \n> > ➜ git fetch --all\n> > Fetching origin\n> > Fetching upstream\n> > remote: Enumerating objects: 23, done.\n> > remote: Counting objects: 100% (23/23), done.\n> > remote: Total 32 (delta 23), reused 23 (delta 23), pack-reused 9\n> > Unpacking objects: 100% (32/32), 12.97 KiB | 949.00 KiB/s, done.\n> > From https://git.foo.com/them/bar\n> >    63f7159..e65b80e  main     -> upstream/main\n> \n> The culprit here is using \"git fetch --all\". It triggers the sub-fetches\n> with --append, so they'll each add to FETCH_HEAD instead of overwriting\n> it.  We do truncate it before the first one, so after this completes it\n> should have the complete set of refs fetched from both remotes (even if\n> it was a noop to fetch one of them, anything mentioned in the refspecs\n> shows up in FETCH_HEAD).\n> \n> Which is what you're seeing here:\n> \n> > ➜ cat .git/FETCH_HEAD\n> > 23e6881719f661c37336d9fcf7a9005a7dfce0cf        not-for-merge   branch 'main' of https://git.foo.com/me/foo\n> > e65b80edd2a2162f67120a98e84bb489f15fcf97                branch 'main' of https://git.foo.com/them/foo\n> \n> FETCH_HEAD is not just a ref, but contains some magic instructions that\n> get interpreted by git-pull. But when programs besides git-pull try to\n> resolve it to a single object, they just pick whichever value is first.\n> \n> So I do think there's a bug there, or at least something not\n> well-thought-out in the way that \"fetch --all\" appends. Normally fetch\n> tries to put the merge branch (or branches) first in the file, exactly\n> so this naive \"take the first one\" lookup will do the most sensible\n> thing. But when running multiple fetches that all append, we get their\n> individual outputs in the order of fetch (which in turn is the same as\n> the order in the config file).\n> \n> Perhaps the parent \"git fetch --all\" triggering the sub-fetches should\n> reorder FETCH_HEAD after they've all finished (to pull any merge heads\n> up to the top, regardless of which remote they came from).\n> \n> But an obvious workaround, if you know you'll always be merging from\n> upstream, is to just reorder your config stanzas so that it's fetched\n> first (likewise you can run \"git fetch --multiple upstream origin\" to\n> specify the order manually, or define a group with remotes.<group>).\n> \n> One reason I suspect nobody has come across this before is that there's\n> not much reason to use FETCH_HEAD in this setting. If you know you want\n> to rebase again upstream/main, then there are a number of ways you can\n> refer to that:\n> \n>   - upstream/main\n> \n>   - upstream, if your refs/remotes/upstream/HEAD is set up (if you\n>     didn't clone, you may want to run \"git remote set-head upstream -a\")\n> \n>   - @{upstream}, if it's configured as your upstream (which it is here)\n> \n>   - @{u}, a shorter synonym\n> \n>   - nothing at all, since rebasing against the upstream is the default\n>     for git-rebase these days\n> \n>   - you can say that (or even just \"upstream\", if your\n>     refs/remotes/origin/HEAD is set up)\n> \n> > Curiously, `git rebase FETCH_HEAD` seems to think the local branch is\n> > up to date (erroneously),\n> \n> That's what I'd expect, since it is doing the naive \"what is the first\n> one in the file\" lookup.\n> \n> > however `git-pull --rebase=true` [works]\n> \n> That is running a new git-fetch under the hood, which will overwrite\n> FETCH_HEAD (and will only fetch from upstream, since that's what's in\n> branch.main.remote).\n> \n> > `git-merge FETCH_HEAD` both work as expected and merge/rebase with\n> > `upstream/main`.\n> \n> I think git-merge, like git-pull, understands the magic FETCH_HEAD\n> format.\n> \n> > Am I going about this incorrectly? The main purpose behind configuring\n> > my \"mostly just a fork\" repository is that it simplifies tracking\n> > against an upstream remote for projects which I do not work on\n> > actively. Of course, you might argue that I don't need to keep my\n> > remote around for this purpose and can just use a straightforward\n> > `git-clone` here -- but I'd rather not, and would prefer responses\n> > addressing the perceived bug rather than suggesting this particular\n> > alternative workflow.\n> \n> I think your workflow is perfectly reasonable.\n> \n> -Peff\n>\n"},{"id":"411364","messageId":"xmqq360lfios.fsf@gitster.c.googlers.com","threadId":"54755","inReplyTo":"112958f6-0eca-453d-86f3-52e7054a88f9@www.fastmail.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-12-04T19:57:23Z","receivedAt":"2020-12-04T19:58:09Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Ben Denhartog\" <ben@sudoforge.com> writes:\n\n> To the rest of your message:\n>\n> I did not understand the behavior of `fetch --all`; what you've\n> described makes sense to me (although I would agree that it sounds\n> like there's a bug). Between the following steps I'll take, I\n> think my fork workflow is \"fixed\":\n>\n> * Refactor away from usage of FETCH_HEAD\n\nYes, \"fetch --all\" is about updating the remote-tracking branches\nand in retrospect, perhaps we might have avoided confusion if we\nmade it not to touch FETCH_HEAD, but it is not going to change now.\n\n> * Set `remote.pushdefault = origin`\n> * Set `push.default = current` (instead of `simple`, and is what\n> my global config sets this to)\n\nI have a feeling that simple vs current does not make a difference\nif you are pusing main to main, and if so, push.default could be\nleft to the default settings of 'simple'.  But the key to successful\nuse of the triangular workflow is to configure so that \"fetch/pull\"\ngoes to one place (i.e. your upstream) and \"push\" goes to another\n(i.e. your publishing repository), and \"remote.pushdefault\" is a\ngood ingredient to do so.\n\nIt is however more common to use 'origin' as the name of your\nupstream repository (so that \"git fetch\" and \"git pull\" would grab\nthings from there by default) and set remote.pushdefault to the\nremote you push into, though (iow, I found remote.pushdefault\npointing at 'origin' a bit unusual).  Doing so may make your\ntriangular workflow work smoother.\n\n> I appreciate your insight and the identification of the problem.\n\nThanks for a concluding comment to report a success.  It's\nreassuring to hear a positive feedback.\n"},{"id":"411401","messageId":"X8qjVAGlrYJWO5fc@coredump.intra.peff.net","threadId":"54755","inReplyTo":"xmqq360lfios.fsf@gitster.c.googlers.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2020-12-04T21:00:04Z","receivedAt":"2020-12-04T21:00:46Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Dec 04, 2020 at 11:57:23AM -0800, Junio C Hamano wrote:\n\n> > * Refactor away from usage of FETCH_HEAD\n> \n> Yes, \"fetch --all\" is about updating the remote-tracking branches\n> and in retrospect, perhaps we might have avoided confusion if we\n> made it not to touch FETCH_HEAD, but it is not going to change now.\n\nI think its behavior of appending all of the entries is sensible (or at\nleast is the least-surprising thing). The only weird part is that it\ndoes not keep the \"make sure heads for merging come before not-for-merge\nentries\" property that individual ones have.\n\nIt could take a final pass after all of the sub-fetches have run and do\nthat. I don't have any plans to work on it, but I'm tempted to call it a\n#leftoverbits candidate.\n\n> > * Set `remote.pushdefault = origin`\n> > * Set `push.default = current` (instead of `simple`, and is what\n> > my global config sets this to)\n> \n> I have a feeling that simple vs current does not make a difference\n> if you are pusing main to main, and if so, push.default could be\n> left to the default settings of 'simple'.  But the key to successful\n> use of the triangular workflow is to configure so that \"fetch/pull\"\n> goes to one place (i.e. your upstream) and \"push\" goes to another\n> (i.e. your publishing repository), and \"remote.pushdefault\" is a\n> good ingredient to do so.\n\nI think my advice is just out-of-date (by quite a lot). In the early\ndays, I remember being bitten by (or at least confused by) simple and\nhow its use of upstream could work with multiple remotes. But we long\nago fixed that, with ed2b18292b (push: change `simple` to accommodate\ntriangular workflows, 2013-06-19), and these days it is explicitly\ndocumented to work the same as \"current\" when pushing to another remote.\n\n> It is however more common to use 'origin' as the name of your\n> upstream repository (so that \"git fetch\" and \"git pull\" would grab\n> things from there by default) and set remote.pushdefault to the\n> remote you push into, though (iow, I found remote.pushdefault\n> pointing at 'origin' a bit unusual).  Doing so may make your\n> triangular workflow work smoother.\n\nYeah, I wasn't going to nitpick his remote names, but that's the same\nconvention I use. :) If people have custom forks of a repository that I\naccess, I usually just name the remote for them after their username\n(including my own).\n\n-Peff\n"},{"id":"411407","messageId":"CAMP44s391U8B5c0iLX84Gqcbg++nbaXs+g_duP82R--JAmLvcA@mail.gmail.com","threadId":"54755","inReplyTo":"601563bf-ed54-4795-917a-fce6e9343b79@www.fastmail.com","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2020-12-04T21:29:43Z","receivedAt":"2020-12-04T21:30:46Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Fri, Dec 4, 2020 at 10:45 AM Ben Denhartog <ben@sudoforge.com> wrote:\n>\n> I'm just now hearing the terminology \"triangular workflow\" (I may live under a rock), but that aptly and succintly describes the workflow I was attempting to simplify with my initial configuration.\n>\n> I read the article on your blog, and the solution you propose makes sense to me, at least in the context of triangular workflows. I don't see any public feedback on your patch; bummer to see. Is it something you've brought up since 2014?\n\nIt did receive some positive public feedback. At least v3 of the series:\n\nhttps://lore.kernel.org/git/xmqq38hkx4lr.fsf@gitster.dls.corp.google.com/\n\nBut my patches have a tendency to enact resistance. Perhaps more so back then.\n\nI have not brought it up since then. I currently have like 4 patch\nseries stuck, doesn't seem wise to add another one. But I likely will\nat some point.\n\nIt is the single most important feature I think Git is lacking. Having\naccustomed myself to the publish branch, I now feel like missing a\nfinger without it on git vanilla.\n\nCheers.\n\n-- \nFelipe Contreras\n"},{"id":"411410","messageId":"64680dc3-1cae-4572-82ef-ed183aff1746@www.fastmail.com","threadId":"54755","inReplyTo":"X8qjVAGlrYJWO5fc@coredump.intra.peff.net","subject":"Re: Unexpected behavior with branch.*.{remote,pushremote,merge}","fromName":"Ben Denhartog","fromEmail":"ben@sudoforge.com","sentAt":"2020-12-04T22:20:32Z","receivedAt":"2020-12-04T22:21:41Z","isPatch":false,"sender":{"key":"ben@sudoforge.com","avatar":null},"body":"I guess from my perspective, for these repositories, my fork _is_ the \"origin\"; I tend to mirror the repositories I contribute to (e.g. use the \"fork\" feature on Git{Hub,Lab}/etc), then clone my mirror, which lends itself to that mental model (origin is \"mine\"). \n\n-- \n  Ben Denhartog\n  ben@sudoforge.com\n\nOn Fri, Dec 4, 2020, at 14:00, Jeff King wrote:\n> On Fri, Dec 04, 2020 at 11:57:23AM -0800, Junio C Hamano wrote:\n> \n> > > * Refactor away from usage of FETCH_HEAD\n> > \n> > Yes, \"fetch --all\" is about updating the remote-tracking branches\n> > and in retrospect, perhaps we might have avoided confusion if we\n> > made it not to touch FETCH_HEAD, but it is not going to change now.\n> \n> I think its behavior of appending all of the entries is sensible (or at\n> least is the least-surprising thing). The only weird part is that it\n> does not keep the \"make sure heads for merging come before not-for-merge\n> entries\" property that individual ones have.\n> \n> It could take a final pass after all of the sub-fetches have run and do\n> that. I don't have any plans to work on it, but I'm tempted to call it a\n> #leftoverbits candidate.\n> \n> > > * Set `remote.pushdefault = origin`\n> > > * Set `push.default = current` (instead of `simple`, and is what\n> > > my global config sets this to)\n> > \n> > I have a feeling that simple vs current does not make a difference\n> > if you are pusing main to main, and if so, push.default could be\n> > left to the default settings of 'simple'.  But the key to successful\n> > use of the triangular workflow is to configure so that \"fetch/pull\"\n> > goes to one place (i.e. your upstream) and \"push\" goes to another\n> > (i.e. your publishing repository), and \"remote.pushdefault\" is a\n> > good ingredient to do so.\n> \n> I think my advice is just out-of-date (by quite a lot). In the early\n> days, I remember being bitten by (or at least confused by) simple and\n> how its use of upstream could work with multiple remotes. But we long\n> ago fixed that, with ed2b18292b (push: change `simple` to accommodate\n> triangular workflows, 2013-06-19), and these days it is explicitly\n> documented to work the same as \"current\" when pushing to another remote.\n> \n> > It is however more common to use 'origin' as the name of your\n> > upstream repository (so that \"git fetch\" and \"git pull\" would grab\n> > things from there by default) and set remote.pushdefault to the\n> > remote you push into, though (iow, I found remote.pushdefault\n> > pointing at 'origin' a bit unusual).  Doing so may make your\n> > triangular workflow work smoother.\n> \n> Yeah, I wasn't going to nitpick his remote names, but that's the same\n> convention I use. :) If people have custom forks of a repository that I\n> access, I usually just name the remote for them after their username\n> (including my own).\n> \n> -Peff\n>\n"}]}