{"thread":{"id":"52000","subject":"Fetch origin/HEAD during git fetch","startedAt":"2019-10-09T01:37:45Z","lastAt":"2019-10-09T14:29:55Z","messageCount":3,"participants":["Dominik Salvet","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"383720","messageId":"CAEXP2g8-reK+u2FaO=mMP-nsvuDDWGpwV_tyKG5L5XpU=1LQeg@mail.gmail.com","threadId":"52000","inReplyTo":null,"subject":"Fetch origin/HEAD during git fetch","fromName":"Dominik Salvet","fromEmail":"dominik.salvet@gmail.com","sentAt":"2019-10-09T01:37:27Z","receivedAt":"2019-10-09T01:37:45Z","isPatch":false,"sender":{"key":"dominik.salvet@gmail.com","avatar":null},"body":"Hello Git community!\nImagine a repository initialised using git init. Then, a remote (e.g.,\norigin) is added. Now, I want to fetch all branches, tags and commits\nfrom the prepared remote to fill the local repository up for the first\ntime and do it as quick as possible. I want the origin/HEAD reference\nto be fetched as well, and this is where the problem is - I don't know\nhow to do it optimally.\n\nTo summarise it, I want the following:\n\n* Prepare a repository as quick as possible\n* No local branches in the repository\n* No files in working tree after downloading\n* Working tree must be available (for further checkouts)\n* Keep the information about its default branch (origin/HEAD)\n* Updates can be fetched using a git fetch (ideally a plain one)\n* The repository will not be ever used for pushing (it does not have\nto be disabled)\n\nThree sub-optimal solutions I have considered:\n\n1) `git fetch origin && git remote set-head origin -a`\n2) `git fetch origin +refs/heads/*:refs/remotes/origin/*\nHEAD:refs/remotes/origin/HEAD`\n3) instead of git init and remote, use directly `git clone --no-checkout`\n\nThe first solution is not suitable due its delay caused by remote\naccess (2 separate invocations). For smaller repositories, delays of\nthese individual commands are almost comparable. However, this\nsolution is semantically exactly what I want.\n\nThe problem with the second solution is that it will create\norigin/HEAD as a commit hash, not as a symbolic reference to a branch\n(e.g., master). When master branch gets updated, it may cause problems\nwith further update fetching using a plain git fetch. Also, this\nsolution doesn't look very familiar and stable.\n\nThe third solution has several problems. The first one is the created\ndefault local branch. So delete it. However, to delete it, I need to\ncheckout another commit and that modifies working tree, which can\ncause unnecessary delay (namely for bigger repositories) as it may\n(and will in most cases) be checked out to another commit later. Then\nI can finally remove the local branch (after getting its name,\nthough).\n\nIf you wonder which applications I need such restrictions for - I am a\ndeveloper of GitPack, a very simple Git-based package manager, and I\nwould like to solve the mentioned problem to improve storing\ndownloaded repositories in GitPack cache. It would allow GitPack\nprojects to use a different default branch than master branch, which\nis currently hard-coded in GitPack.\n\nI hope everything is clear. If not, do not hesitate and ask me. I\nwould really appreciate your help.\n\nThank you for all your effort\n-- \nDominik Salvet\n"},{"id":"383727","messageId":"20191009022457.GB73710@google.com","threadId":"52000","inReplyTo":"CAEXP2g8-reK+u2FaO=mMP-nsvuDDWGpwV_tyKG5L5XpU=1LQeg@mail.gmail.com","subject":"Re: Fetch origin/HEAD during git fetch","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2019-10-09T02:24:57Z","receivedAt":"2019-10-09T02:25:01Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi!\n\nDominik Salvet wrote:\n\n> 1) `git fetch origin && git remote set-head origin -a`\n> 2) `git fetch origin +refs/heads/*:refs/remotes/origin/*\n> HEAD:refs/remotes/origin/HEAD`\n> 3) instead of git init and remote, use directly `git clone --no-checkout`\n>\n> The first solution is not suitable due its delay caused by remote\n> access (2 separate invocations). For smaller repositories, delays of\n> these individual commands are almost comparable. However, this\n> solution is semantically exactly what I want.\n\nInteresting.\n\nFor the specific case, it sounds like some kind of \"git fetch\n--also-set-head\" would do the trick for you.  As you can see, I'm awful\nat naming command line options --- aside from the need to give it a\nbetter name, any others thoughts on that?  Would you be interested in\ntaking a stab at implementing it?\n\nFor the more general case, there's been some discussion of fetching\nand pushing symrefs on-list before.  [1] discusses one possible UI.\n\n[...]\n> The third solution has several problems. The first one is the created\n> default local branch. So delete it.\n\nHm, I don't follow.  Does \"git checkout --orphan\" do what you're\nlooking for?\n\nThanks and hope that helps,\nJonathan\n\n[1] https://public-inbox.org/git/20180814214723.GA667@sigill.intra.peff.net/\n"},{"id":"383753","messageId":"CAEXP2g93XtaeEZi-5+A+PEDT7FJgJERdsrsAG7OFqWpShD7mqw@mail.gmail.com","threadId":"52000","inReplyTo":"20191009022457.GB73710@google.com","subject":"Re: Fetch origin/HEAD during git fetch","fromName":"Dominik Salvet","fromEmail":"dominik.salvet@gmail.com","sentAt":"2019-10-09T14:29:33Z","receivedAt":"2019-10-09T14:29:55Z","isPatch":false,"sender":{"key":"dominik.salvet@gmail.com","avatar":null},"body":"Hi Jonathan,\nThank you for your time. I would be for something like `git fetch\n--head` or `git fetch --remote-head` as the name. It also matches `git\nfetch --tags` - fetch tags from remote, in addition to whatever else.\nAside from that, there are no further comments from my side. I would\nbe really happy to see the option in newer versions of Git (though, I\nwould be more happier being able to implement it in current ones...).\nHowever, I won't be able to implement it myself for two reasons; a)\nnot enough skill in C and b) unfortunately, I do not have enough time.\nNevertheless, I can assist during the development of this feature if\napproved and if there is someone who actually writes the code.\n\nAnother solution, on the other hand, could be the one from the\nprovided link [1] - use ~ for symrefs. That would also solve my\nproblem and since it would be equivalent to `git remote set-head\norigin -a`, I am perfectly fine with that. Just run `git config --add\nremote.origin.fetch ~HEAD:refs/remotes/origin/HEAD` after setting up\nthe origin remote and then just use `git fetch`.\n\nAbout the `git checkout --orphan`: it also modifies the work tree in\nmy case (files in local repository), which I don't want to. Still, if\nI want to create a branch to delete another branch (default clone\nlocal branch), that itself is counterproductive - I don't want any\nlocal branches. There is another problem, though. What name to choose\nfor `git checkout --orphan <name>` not to conflict with a default\nbranch (that could be anything) of the repository? Yep, there is a\nsolution for that but I don't want to make things over-complicated. I\nwould rather not use the `git clone` solution as long as there is no\n`git clone --no-checkout-and-no-local-branches`-like option/s.\n\nHowever, it looks like I have found an optimal workaround for my case.\nUse git init, setup git remote and also run `git config --add\nremote.origin.fetch HEAD:refs/remotes/origin/HEAD`. Now, using a plain\n`git fetch` for fetching updates also fetches the current default\nremote commit in origin/HEAD each time used, so no symbolic reference\nto a branch might not be required as origin/HEAD points to the latest\ncommit of the default branch in both cases. Symbolic reference may be\nbeneficient in case when not fetching origin/HEAD while fetching the\nbranch pointed by origin/HEAD reference, which may fail in case the\nremote updates its origin/HEAD anyways (e.g., on GitHub - repository\nSettings -> Branches -> Default branch).\n\nDue to my workaround, I guess now it's up to you, developers, whether\ndeveloping a `git fetch --head` option or ~ for symrefs worth it for\nyou. Anyway, if you find any pitfalls in my workaround, please let me\nknow. If you are rather interested in the actual implementation, take\na look at GitPack hosted on github.com/dominiksalvet/gitpack, the\naffected file is src/gitpack (search for 'git config').\n\nHave a nice day,\n\nOn Wed, 9 Oct 2019 at 04:25, Jonathan Nieder <jrnieder@gmail.com> wrote:\n>\n> Hi!\n>\n> Dominik Salvet wrote:\n>\n> > 1) `git fetch origin && git remote set-head origin -a`\n> > 2) `git fetch origin +refs/heads/*:refs/remotes/origin/*\n> > HEAD:refs/remotes/origin/HEAD`\n> > 3) instead of git init and remote, use directly `git clone --no-checkout`\n> >\n> > The first solution is not suitable due its delay caused by remote\n> > access (2 separate invocations). For smaller repositories, delays of\n> > these individual commands are almost comparable. However, this\n> > solution is semantically exactly what I want.\n>\n> Interesting.\n>\n> For the specific case, it sounds like some kind of \"git fetch\n> --also-set-head\" would do the trick for you.  As you can see, I'm awful\n> at naming command line options --- aside from the need to give it a\n> better name, any others thoughts on that?  Would you be interested in\n> taking a stab at implementing it?\n>\n> For the more general case, there's been some discussion of fetching\n> and pushing symrefs on-list before.  [1] discusses one possible UI.\n>\n> [...]\n> > The third solution has several problems. The first one is the created\n> > default local branch. So delete it.\n>\n> Hm, I don't follow.  Does \"git checkout --orphan\" do what you're\n> looking for?\n>\n> Thanks and hope that helps,\n> Jonathan\n>\n> [1] https://public-inbox.org/git/20180814214723.GA667@sigill.intra.peff.net/\n\n\n\n--\nDominik Salvet\n"}]}