{"thread":{"id":"59265","subject":"Git pull without fetch","startedAt":"2023-02-18T00:09:13Z","lastAt":"2023-02-18T04:36:31Z","messageCount":4,"participants":["ronan@rjp.ie","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"472284","messageId":"49c07b5dc2afbd422d492d59380ad2c2@rjp.ie","threadId":"59265","inReplyTo":null,"subject":"Git pull without fetch","fromName":"","fromEmail":"ronan@rjp.ie","sentAt":"2023-02-18T00:09:05Z","receivedAt":"2023-02-18T00:09:13Z","isPatch":false,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"Dear maintainers,\n\nI use the git-maintenance prefetch task with a certain repo to periodically\nfetch updates from the remote. I'm trying to figure out a way to have git\n\"complete\" a prefetch on command, via an option, alias, or other extension that\nmimics the behavior of git pull, but does not fetch from the remote. By\ncomparison, `git pull` or `git fetch && git rebase` would fetch the remote and\nfast-forward my local copy to match, but I don't want to fetch the remote.\nInstead I want to fast-forward my current branch (and the remote tracking\nbranch) to the prefetched tip as if git pull had been run at the time of the\nlast prefetch.\n\nFor example, suppose my local copy has a branch master that tracks the remote\nbranch master from origin. Suppose that the local copy (and the remote tracking\nbranch) have commits A--B, the remote has commits A--B--C--D, and commit C has\nbeen prefetched and is pointed to by refs/prefetch/remotes/origin/master. The\ndesired effect could be accomplished, I think, by:\n\ngit update-ref refs/remotes/origin/master refs/prefetch/remotes/origin/master refs/heads/master &&\ngit rebase origin/master master\n\nMy question is, how can I calculate the correct remote tracking branch to\naccomplish this operation in the general case, just as git pull without argument\nwould have done? Or is there a simpler way to achieve my goal?\n\nCheers,\nRonan\n"},{"id":"472288","messageId":"fc7d9fdde0443532eb9c32f26f9f054e@rjp.ie","threadId":"59265","inReplyTo":"CAPx1Gvd8vizeyveKgE2o2GStQsiGxN4aaASqYc81Nk28ogFLJg@mail.gmail.com","subject":"Re: Git pull without fetch","fromName":"","fromEmail":"ronan@rjp.ie","sentAt":"2023-02-18T02:02:21Z","receivedAt":"2023-02-18T02:02:25Z","isPatch":false,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"February 17, 2023 6:46 PM, \"Chris Torek\" <chris.torek@gmail.com> wrote:\n\n> `git pull` = `git fetch` followed by a second command, either `git merge` or `git rebase`. If you\n> don't want the `git fetch` step, run the *second* command, instead of running *both* commands: it's\n> really just that simple.\n\nNo it isn't. Sorry, but I think you have misunderstood the problem. I'm well\naware of the behavior of git pull.\n\nIn the scenario described, `git rebase` will always report \"Already up to date\"\nbecause the head of the current branch and the head of the remote tracking\nbranch are the same. The prefetched reference lives under refs/prefetch/* and is\nunnoticed by git rebase. This is why I used `git update-ref ...` first: to\nupdate the remote tracking branch from the prefetched copy.\n"},{"id":"472289","messageId":"xmqqo7prk7vj.fsf@gitster.g","threadId":"59265","inReplyTo":"fc7d9fdde0443532eb9c32f26f9f054e@rjp.ie","subject":"Re: Git pull without fetch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-02-18T02:46:56Z","receivedAt":"2023-02-18T02:47:00Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"ronan@rjp.ie writes:\n\n> In the scenario described, `git rebase` will always report \"Already up to date\"\n> because the head of the current branch and the head of the remote tracking\n> branch are the same. The prefetched reference lives under refs/prefetch/* and is\n> unnoticed by git rebase. This is why I used `git update-ref ...` first: to\n> update the remote tracking branch from the prefetched copy.\n\nThat is very much working as designed.  Prefetching is merely a\nperformance thing---until the user explicitly says \"I want to update\nmy view of the other side by fetching and updating the remote\ntracking branches\" with \"git fetch\", it will not disrupt\nrefs/remotes/origin/* refs, and because of prefetching, when the\nuser finally gets around to say that, observation of the other side\nwith a real fetch would go faster, requiring fewer objects to be\ntransmit.\n\nAnd if somebody wants to lie to the system and say \"pretend we did\nnot fetch anything\", then yes, _knowing_ that implementation detail\nof refs/prefetch/* hierarchy and taking advantage of it by using\n\"update-ref\" would be a way to achieve that.\n"},{"id":"472294","messageId":"2aff5436d69e09241bee775cf03e9723@rjp.ie","threadId":"59265","inReplyTo":"xmqqo7prk7vj.fsf@gitster.g","subject":"Re: Git pull without fetch","fromName":"","fromEmail":"ronan@rjp.ie","sentAt":"2023-02-18T04:33:59Z","receivedAt":"2023-02-18T04:36:31Z","isPatch":false,"sender":{"key":"ronan@rjp.ie","avatar":"https://avatars.githubusercontent.com/u/12577529?v=4"},"body":"> That is very much working as designed.\n\nYes, I realize. I'm not reporting a bug. I guess I just think it would be handy\nto more conveniently reach the prefetched updates when I'm offline, and I gather\nfrom conversation there is no method builtin to git.\n\nFor now I've settled on this to be \"pretend fetch\":\n\n$ git for-each-ref refs/prefetch/ --format='update refs/%(refname:lstrip=2) (refname)' | git update-ref --stdin\n\nwhich I can follow-up with a no-argument `git rebase`, similar to a `git pull`\nif the remote was available.\n\nIn my original question I had intended only to update the upstream of my current\nbranch, but I've decided that's not necessary for me. However, I have found that\nit is possible to get the upstream reference for the current branch like so:\n\n$ git rev-parse --symbolic-full-name '@{upstream}' refs/remotes/origin/master\n\nusing this it should be possible to find the corresponding prefetched reference\nin refs/prefetch if it exists and only update that reference without parsing\n\"branch.<name>.remote\", \"remote.<name>.fetch\", and \"branch.<name>.merge\" myself.\n"}]}