git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git clone (ssh://) skips detached HEAD

From
Jeff King <peff@peff.net>
Date
Jun 3, 2011, 18:48 UTC
Message-ID
<20110603184822.GA20600@sigill.intra.peff.net>
In-Reply-To
<7vaadyc2u0.fsf@alter.siamese.dyndns.org>
On Fri, Jun 03, 2011 at 09:11:19AM -0700, Junio C Hamano wrote:
Show 9 quoted lines
> An alternative would be not to checkout anything when HEAD points at an
> object that does not exist, or point the HEAD at the default "master"
> branch just like in the case when we cannot guess uniquely. That way, we
> do not have to worry about having to fetch the orphaned detached HEAD,
> which is an unlikely thing the publisher wanted to feed to its recipients
> in the first place. I tend to prefer the former (i.e. resulting in no
> paths in the working tree, possibly with a big warning message "the
> repository does not suggest which branch to track---are you sure you
> wanted to clone from there?").

Yeah, I was tempted to go the "check out nothing if we don't have the object" route. But my thinking was:

  1. We have already been creating local detached HEADs to match a
     remote detached HEAD since at least 8434c2f (Build in clone,
     2008-04-27). Should we keep doing that? If so, I think it
     introduces a somewhat confusing inconsistency from the user's
     perspective. Why is a sight-seeing detached HEAD pointing into
     history OK to checkout, but one with a commit on top is not OK?
  2. Similar to the above, we already do have the object for a local
     clone, which just copies the object db whole. So now there is an
     inconsistency that:
       git clone foo bar
     will checkout out such a HEAD, but neither of:
       git clone file://$PWD/foo bar
       git clone git://host/foo bar
     does.
  3. Fetching and checking it out just seems like the most friendly and
     the least surprising thing for the user. In 99% of cases, people
     are cloning bare repositories whose HEADs likely won't detach
     anyway (and if they did, they certainly wouldn't have made commits
     on them). But in the rare case that I _do_ clone a non-bare repo,
     what am I trying to accomplish?
     Most likely I'm trying to make a new workspace, either to work on
     the identical branch, or some other branch. In the former case,
     making a detached HEAD (whether it points to history or to a new
     commit) is what I would want. In the latter case, it doesn't really
     matter what we put in HEAD, as the user is going to switch it
     anyway. The only downside is that we may have transferred some
     extra objects; in practice, this is probably not a big deal due to
     deltas unless your detached commit is gigantic.
  4. We're guessing at whether the user will want the objects on the
     detached HEAD or not. Which means we're going to be wrong
     sometimes. But I would rather err on the side of copying the extra
     commits than not. The few extra bytes spent are a better downside
     than:
       $ git clone git://host/foo bar
       $ ssh host && rm -rf foo
       [oops, I actually wanted the detached commit!]
     Though to be fair, if we printed a warning about the detached HEAD
     during the first command, the user would hopefully not execute the
     second one.
> We treat the symbolic-ref on the publishing end not as the "current"
> branch at all. It is used as the "suggested primary branch to track".
> So allowing to fetch from a repository with detached HEAD is already a
> weird setup.

By that argument, we should stop checking out any detached HEAD at all. Which I agree makes sense from the point of view that clone is just "init + remote add + fetch + checkout". But I think it's probably more helpful to the user (and doesn't cost us much) to just checkout the detached HEAD than to refuse to check out anything and print a warning. If we're right, they're happy. If we're wrong, the solution in both cases is to "git checkout" what they did want.

Possibly we should warn that the cloned HEAD is detached (maybe even with the regular detached HEAD warning).

> I am hoping that we are not setting up origin/HEAD to point at
> anything in this case, as the remote is telling us that there is no
> suggested primary branch for the clients to track by having a detached
> HEAD to begin with.

No, we don't set up an origin/HEAD at all in that case; the handling for that and our local HEAD are separate (and I was careful to maintain this with my patch by not setting a peer_ref to store the HEAD we fetch; it stays in core until we write it to our HEAD).

Show 6 quoted lines
> Even if you are fetching your own (or your pal's) repository with a
> working tree to transfer a work-in-progress, any work on detached HEAD
> that is orphaned is too transitory, and it goes against my taste to
> let people fetch from it.
> 
> But people are free to have bad taste ;-).

They can already fetch from it via "git fetch /your/pal HEAD". So this is really just about clone. I think it is not even bad taste if your workflow is:

  1. You're in the middle of a rebase on a detached HEAD. You make an
     amended commit, then continue. You get a conflict which is
     confusing, and inspection causes you to blame your coworker.
  2. You holler over the cubicle wall to your coworker, who runs "git
     clone ~bob/project bobs-project". They inspect your current state
     and try to cherry-pick the failed commit themselves. Either the
     merge conflicts tell them what to tell you to fix your problem, or
     perhaps they even resolve the conflicts themselves and let you
     fetch the state back.

So I think it is not a matter of taste, but of "in some (rare) cases this is useful, and in many cases it is useless". I just think there is no reason not to be helpful to the people in the rare cases, as it costs so little in the other case (and remember that _without_ detached orphan commits, this is literally a no-op).

-Peff
Previous: Junio C HamanoNext: Jakub Narebski
Message 61 of 65 in “git clone (ssh://) skips detached HEAD”
  1. Dmitry IvankovJun 1, 2011
  2. Jeff KingJun 1, 2011
  3. Dmitry IvankovJun 1, 2011
  4. Junio C HamanoJun 1, 2011
  5. Jeff KingJun 1, 2011
  6. Jeff KingJun 1, 2011
  7. Jeff KingJun 3, 2011
  8. 1/3 t: add tests for cloning remotes with detached HEADJeff King, Jun 3, 2011
  9. 2/3 consider only branches in guess_remote_headJeff King, Jun 3, 2011
  10. 3/3 clone: always fetch remote HEADJeff King, Jun 3, 2011
  11. Sverre RabbelierJun 3, 2011
  12. Jeff KingJun 3, 2011
  13. Jeff KingJun 3, 2011
  14. Junio C HamanoJun 3, 2011
  15. Jeff KingJun 3, 2011
  16. Sverre RabbelierJun 4, 2011
  17. Jeff KingJun 6, 2011
  18. Junio C HamanoJun 6, 2011
  19. Junio C HamanoJun 6, 2011
  20. Sverre RabbelierJun 6, 2011
  21. Junio C HamanoJun 6, 2011
  22. Jeff KingJun 6, 2011
  23. Sverre RabbelierJun 6, 2011
  24. Jeff KingJun 7, 2011
  25. Sverre RabbelierJun 7, 2011
  26. 0/8 minor import/export remote helper fixesJeff King, Jun 7, 2011
  27. 1/8 transport-helper: fix minor leak in push_refs_with_exportJeff King, Jun 7, 2011
  28. 2/8 git-remote-testgit: exit gracefully after pushJeff King, Jun 7, 2011
  29. Sverre RabbelierJun 7, 2011
  30. 3/8 t5800: factor out some ref testsJeff King, Jun 7, 2011
  31. Sverre RabbelierJun 7, 2011
  32. 4/8 t5800: document some non-functional parts of remote helpersJeff King, Jun 7, 2011
  33. Sverre RabbelierJun 7, 2011
  34. Jeff KingJun 7, 2011
  35. Sverre RabbelierJun 7, 2011
  36. Jeff KingJun 7, 2011
  37. Sverre RabbelierJun 7, 2011
  38. Jeff KingJun 7, 2011
  39. Junio C HamanoJun 8, 2011
  40. Jeff KingJun 9, 2011
  41. Junio C HamanoJun 9, 2011
  42. Jeff KingJun 9, 2011
  43. Sverre RabbelierJun 9, 2011
  44. 5/8 teach remote-testgit to import non-HEAD refsJeff King, Jun 7, 2011
  45. Junio C HamanoJun 8, 2011
  46. Jeff KingJun 9, 2011
  47. 6/8 teach remote-testgit to import multiple refsJeff King, Jun 7, 2011
  48. 7/8 transport-helper: don't feed bogus refs to export pushJeff King, Jun 7, 2011
  49. Sverre RabbelierJun 7, 2011
  50. 8/8 git_remote_helpers: push all refs during a non-local exportJeff King, Jun 7, 2011
  51. Sverre RabbelierJun 7, 2011
  52. Jeff KingJun 7, 2011
  53. Sverre RabbelierJun 7, 2011
  54. Junio C HamanoJun 6, 2011
  55. Jeff KingJun 6, 2011
  56. Jeff KingJun 7, 2011
  57. 1/2 make copy_ref globally availableJeff King, Jun 7, 2011
  58. 2/2 clone: always fetch remote HEADJeff King, Jun 7, 2011
  59. Junio C HamanoJun 7, 2011
  60. Junio C HamanoJun 3, 2011
  61. Jeff KingJun 3, 2011
  62. Jakub NarebskiJun 1, 2011
  63. Jeff KingJun 1, 2011
  64. Jakub NarebskiJun 2, 2011
  65. Jeff KingJun 3, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.