Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

20 messages, 10 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:47:33

Nicolas Pitre [off-list ref] writes:
On Wed, 14 Oct 2009, Junio C Hamano wrote:
quoted
Nicolas Pitre [off-list ref] writes:
quoted
On Wed, 14 Oct 2009, Daniel Barkalow wrote:
quoted
On Wed, 14 Oct 2009, Jay Soffian wrote:
quoted
$ git commit -m "blah"
Cannot commit while not on any branch. Please use git commit -b <branch> to
specify the name of a new branch to commit to, or use git commit -f to
force a detached commit.
The difference is that some experienced users depend on being able to 
commit while not on a branch, and want to not get a warning for every 
commit while not on a branch.
I assume that the -f would silence any warning?
It won't help to alleviate my irritation if I need to give -f to each and
every invocation of "git commit" while detached, though.
Agreed.  Presumably some expert mode config would imply -f 
automatically.
No, I do not want an expert mode.  I can probably live with "per session"
setting, that makes me decide to set or not set it when I detach, though.

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Jeff King <hidden>
Date: 2016-06-15 22:47:33

On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote:
quoted
Agreed.  Presumably some expert mode config would imply -f 
automatically.
No, I do not want an expert mode.  I can probably live with "per session"
setting, that makes me decide to set or not set it when I detach, though.
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

  $ git checkout --detach=commit origin/master
  $ git commit ;# should be ok

  $ git checkout --detach=examine origin/master
  $ git commit ;# complain
  $ git checkout --detach=commit HEAD
  $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.

-Peff

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2016-06-15 22:47:33

On Wed, 14 Oct 2009, Jeff King wrote:
On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote:
quoted
quoted
Agreed.  Presumably some expert mode config would imply -f 
automatically.
No, I do not want an expert mode.  I can probably live with "per session"
setting, that makes me decide to set or not set it when I detach, though.
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

  $ git checkout --detach=commit origin/master
  $ git commit ;# should be ok

  $ git checkout --detach=examine origin/master
  $ git commit ;# complain
  $ git checkout --detach=commit HEAD
  $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
Whatever is done about this... I'm afraid Git will end up less useful as 
operations that were possible before won't be anymore for "security's 
sake" unless some obnoxious override mode is involved.

Isn't the reflog already dealing with the security issue by making sure 
that nothing is "lost"?

Can't the user confusion be dealt with through some means other than 
making the tool less flexible?  I don't mind extra help message to be 
displayed after a headless commit is made for example.  But trying to 
make the tool more friendly should perhaps come from better education 
rather than added restrictions.

My thoughts only.


Nicolas

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: James Pickens <hidden>
Date: 2016-06-15 22:47:33

On Wed, Oct 14, 2009 at 4:09 PM, Jeff King [off-list ref] wrote:
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

 $ git checkout --detach=commit origin/master
 $ git commit ;# should be ok

 $ git checkout --detach=examine origin/master
 $ git commit ;# complain
 $ git checkout --detach=commit HEAD
 $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain

$ git checkout v1.0.1
$ git status
# On tag v1.0.1
$ git commit ;# complain

$ git checkout v1.0.1^0 ;# detach
$ git commit ;# ok

I think this would help the newbies and wouldn't cost the experts too much.
Checking out anything other than a plain ref would still detach the head, and
commits on a detached head would still be allowed.  Perhaps as an additional
safety feature, Git could refuse to switch away from a detached head if the head
isn't reachable from any ref, and require -f to override:

$ git checkout $sha1
$ git commit
$ git checkout master ;# complain
$ git checkout -f master ;# ok

Maybe I'm missing something and this all can't be done, but it seems simpler
than the other options I've seen in this thread.

James

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:47:33

James Pickens [off-list ref] writes:
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain

$ git checkout v1.0.1
$ git status
# On tag v1.0.1
$ git commit ;# complain

$ git checkout v1.0.1^0 ;# detach
$ git commit ;# ok

I think this would help the newbies and wouldn't cost the experts too much.
Checking out anything other than a plain ref would still detach the head, and
commits on a detached head would still be allowed.
I think it is a very good idea.

This makes it easy to checkout remote-tracking branch or a tag for
viewing, something that was (I think) one of problems (use cases) that
lead to invention of detached HEAD... and then it turned out that
detached HEAD (unnamed branch) is scary for newbie git users.  (So the
difficulty of having to create new branch or rewind some branch to
view non-committable ref was replaced by scary detached HEAD concept.)

With this idea there are no problems with git commands that use
detached HEAD such as git-bisect (which uses it in viewing mode, but
then skips through history, so detached HEAD is a good solution here)
or git-rebase (which does committing on detached HEAD for easier
aborting and cleanup).


Let me propose additional feature: "smart" (context sensitive)
warnings, namely that in the following sequence

  $ git checkout origin/master
  $ git status
  # On remote-tracking branch origin/master of remote origin
  # ...

  $ git commit

'git commit' would refuse committing on non-heads ref, and propose,
beside _always_ proposing detaching HEAD and committing on such
detached HEAD (unnamed branch) via "git checkout HEAD^0", or
"git checkout --detach [HEAD]":

1. If there is no local branch which follows 'origin/master'
   (which has 'origin/master' as upstream, which tracks 'origin/master')
   propose creating it before comitting:

    $ git checkout -t origin/master

2. If there is single local branch that follows 'origin/master',
   and it fast-forwards to 'origin/master' propose... 
   errr, something that would mean fast-forwarding this branch
   and making a commit on local branch that has 'origin/master'
   as upstream.
   
3. If there is single local branch that follows 'origin/master', but
   it has changes / diverges from 'origin/master' we are viewing,
   propose... hmmm, what then?

4. If there are more than one local branch that has 'origin/master'
   as upstream, list all those branches in message.
Perhaps as an additional safety feature, Git could refuse to switch
away from a detached head if the head isn't reachable from any ref,
and require -f to override:

$ git checkout $sha1
$ git commit
$ git checkout master ;# complain
$ git checkout -f master ;# ok

Maybe I'm missing something and this all can't be done, but it seems simpler
than the other options I've seen in this thread.
I'm not sure about overloading '-f' option, unless we would require
doubled '-f' for overriding both safety checks: checkout from detached
HEAD, and current meaning of forcing a switch even if index or the
working are differs from HEAD.  So you would need

  $ git checkout -f -f master

if you are on detached HEAD and have uncommitted changes (dirty tree 
or dirty index).

-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Björn Steinbrink <hidden>
Date: 2016-06-15 22:47:33

On 2009.10.15 05:54:52 -0700, Jakub Narebski wrote:
James Pickens [off-list ref] writes:
quoted
Perhaps as an additional safety feature, Git could refuse to switch
away from a detached head if the head isn't reachable from any ref,
and require -f to override:

$ git checkout $sha1
$ git commit
$ git checkout master ;# complain
$ git checkout -f master ;# ok

Maybe I'm missing something and this all can't be done, but it seems simpler
than the other options I've seen in this thread.
I'm not sure about overloading '-f' option, unless we would require
doubled '-f' for overriding both safety checks: checkout from detached
HEAD, and current meaning of forcing a switch even if index or the
working are differs from HEAD.  So you would need

  $ git checkout -f -f master

if you are on detached HEAD and have uncommitted changes (dirty tree 
or dirty index).
A dirty index/worktree doesn't necessarily stop you from checking out a
different branch head/commit. Only if you have uncommitted changes to a
file that also has changes between HEAD and <other_branch>, git refuses
to switch. And if you want to keep your uncommitted changes, you want to
use -m (3-way merge), not -f (drop changes).

git checkout -f foo ~= git reset --hard && git checkout foo

So -f is most likely _not_ the flag one wants to overload.

Björn

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, James Pickens wrote:
On Wed, Oct 14, 2009 at 4:09 PM, Jeff King [off-list ref] wrote:
quoted
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

 $ git checkout --detach=commit origin/master
 $ git commit ;# should be ok

 $ git checkout --detach=examine origin/master
 $ git commit ;# complain
 $ git checkout --detach=commit HEAD
 $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain

$ git checkout v1.0.1
$ git status
# On tag v1.0.1
$ git commit ;# complain

$ git checkout v1.0.1^0 ;# detach
$ git commit ;# ok

I think this would help the newbies and wouldn't cost the experts too much.
Checking out anything other than a plain ref would still detach the head, and
commits on a detached head would still be allowed.
I think reducing users' exposure to the "detached HEAD" state would just 
make it take longer for them to find that state familiar.

It's not like the concept is actually very difficult or unusual. CVS has 
it as "cvs checkout -r <something>" or "cvs checkout -D <something>"; SVN 
has it as "svn checkout -r <something>". It was weird and scary in CVS if 
you did it (it was "sticky tags", and you had to find a different option 
to get back to normal), but SVN is easier ("svn checkout -r HEAD").

I think the description used in CVS and SVN (and, I think, others) is that 
you're not at the HEAD revision. I think they both account for the state 
where you've checked out the revision by number that's the latest 
revision, but you still can't grow the branch because you can't 
simultaneously stay on r1000 (as requested explicitly) and add a new 
commit.

So maybe the right explanation is:

$ git checkout master; git branch
* master
$ git checkout origin/master; git branch
* origin/master (not at head)
$ git checkout 123cafe^5; git branch
* 123cafe^5 (not at head)
$ git checkout HEAD^2; git branch
* 123cafe^5^2
$ git commit; git branch
* (temporary branch)

Then we can say that one way that git is different from SVN is that all 
branches of other repositories are read-only, and you can't be at the 
head when you're on them (because the head of those branches are in 
different repositories); instead you grow the history locally, and you 
tell the remote branch to adopt your history.
Perhaps as an additional safety feature, Git could refuse to switch away 
from a detached head if the head isn't reachable from any ref
As far as I know, people don't actually seem to lose stuff this way. In 
part, that's because they get scared before they get there; in part, 
that's because they just don't think to go there; and in part, we tell 
them how to recover stuff at that point (using the ref log or the sha1).

	-Daniel
*This .sig left intentionally blank*

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:47:33

Daniel Barkalow venit, vidit, dixit 15.10.2009 17:36:
On Thu, 15 Oct 2009, James Pickens wrote:
quoted
On Wed, Oct 14, 2009 at 4:09 PM, Jeff King [off-list ref] wrote:
quoted
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

 $ git checkout --detach=commit origin/master
 $ git commit ;# should be ok

 $ git checkout --detach=examine origin/master
 $ git commit ;# complain
 $ git checkout --detach=commit HEAD
 $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain

$ git checkout v1.0.1
$ git status
# On tag v1.0.1
$ git commit ;# complain

$ git checkout v1.0.1^0 ;# detach
$ git commit ;# ok

I think this would help the newbies and wouldn't cost the experts too much.
Checking out anything other than a plain ref would still detach the head, and
commits on a detached head would still be allowed.
I think reducing users' exposure to the "detached HEAD" state would just 
make it take longer for them to find that state familiar.
Yep. Which is why I keep suggesting that git clone does not create any
local branches at all ;)
It's not like the concept is actually very difficult or unusual. CVS has 
it as "cvs checkout -r <something>" or "cvs checkout -D <something>"; SVN 
has it as "svn checkout -r <something>". It was weird and scary in CVS if 
you did it (it was "sticky tags", and you had to find a different option 
to get back to normal), but SVN is easier ("svn checkout -r HEAD").
svn up -r HEAD
I think the description used in CVS and SVN (and, I think, others) is that 
you're not at the HEAD revision. I think they both account for the state 
where you've checked out the revision by number that's the latest 
revision, but you still can't grow the branch because you can't 
simultaneously stay on r1000 (as requested explicitly) and add a new 
commit.
I'd say the fundamental difference is that in CVS and SVN, there is
always only one "tip", which they call HEAD. This is also why revision
numbers make sense.

In git and hg there can be many tips (branch heads) from which to grow
the DAG. Heck, you can grow a new one from any commit ;)
So maybe the right explanation is:

$ git checkout master; git branch
* master
$ git checkout origin/master; git branch
* origin/master (not at head)
Ouch, please don't. HEAD has a completely different meaning in git. I
know you know, of course.
$ git checkout 123cafe^5; git branch
* 123cafe^5 (not at head)
$ git checkout HEAD^2; git branch
* 123cafe^5^2
$ git commit; git branch
* (temporary branch)

Then we can say that one way that git is different from SVN is that all 
branches of other repositories are read-only, and you can't be at the 
head when you're on them (because the head of those branches are in 
different repositories); instead you grow the history locally, and you 
tell the remote branch to adopt your history.
You can change your refs/remotes/origin/master, of course, it's just by
convention (for a good reason) that git treats them as read-only, and
porc. respects that.

git's branches are simply completely different, they're movable tags,
and I think that's one point new users *have* to grok. Once they're over
this then even detached heads are a natural thing.
quoted
Perhaps as an additional safety feature, Git could refuse to switch away 
from a detached head if the head isn't reachable from any ref
As far as I know, people don't actually seem to lose stuff this way. In 
part, that's because they get scared before they get there; in part, 
that's because they just don't think to go there; and in part, we tell 
them how to recover stuff at that point (using the ref log or the sha1).
Maybe we just don't scare them enough yet :)

Michael

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, James Pickens wrote:
On Wed, Oct 14, 2009 at 4:09 PM, Jeff King [off-list ref] wrote:
quoted
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

 $ git checkout --detach=commit origin/master
 $ git commit ;# should be ok

 $ git checkout --detach=examine origin/master
 $ git commit ;# complain
 $ git checkout --detach=commit HEAD
 $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain

$ git checkout v1.0.1
$ git status
# On tag v1.0.1
$ git commit ;# complain

$ git checkout v1.0.1^0 ;# detach
$ git commit ;# ok

I think this would help the newbies and wouldn't cost the experts too much.
I agree.
Checking out anything other than a plain ref would still detach the 
head, and commits on a detached head would still be allowed.  Perhaps 
as an additional safety feature, Git could refuse to switch away from 
a detached head if the head isn't reachable from any ref, and require 
-f to override:

$ git checkout $sha1
$ git commit
$ git checkout master ;# complain
$ git checkout -f master ;# ok
Nah.  This is obnoxious.  The usual "this is not a local branch" warning 
could be displayed at that point, and if one really ignores the warning 
then any commit made that way is always reachable through the reflog.  
You would have had to work a bit harder to detach HEAD already anyway, 
so at that point you're not supposed to be such a newbie anymore.
Maybe I'm missing something and this all can't be done, but it seems simpler
than the other options I've seen in this thread.
It is indeed simpler.  It makes the checkout command less verbose as 
well.  Only the commit command would need to warn the user and only if a 
forbidden operation is attempted (like committing on a non 
refs/heads/*). I think I like this.


Nicolas

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, Jakub Narebski wrote:
James Pickens [off-list ref] writes:
quoted
I think this would help the newbies and wouldn't cost the experts too much.
Checking out anything other than a plain ref would still detach the head, and
commits on a detached head would still be allowed.
I think it is a very good idea.

This makes it easy to checkout remote-tracking branch or a tag for
viewing, something that was (I think) one of problems (use cases) that
lead to invention of detached HEAD... and then it turned out that
detached HEAD (unnamed branch) is scary for newbie git users.  (So the
difficulty of having to create new branch or rewind some branch to
view non-committable ref was replaced by scary detached HEAD concept.)
I don't think detached head is scary at all (unless viewed in another 
context other than git) but if that encounter can be kept away from most 
users without denying its use then all for the better.
With this idea there are no problems with git commands that use
detached HEAD such as git-bisect (which uses it in viewing mode, but
then skips through history, so detached HEAD is a good solution here)
or git-rebase (which does committing on detached HEAD for easier
aborting and cleanup).
I do like and actively use manual committing on a detached HEAD as well, 
so please let's not forget about that use case.
Let me propose additional feature: "smart" (context sensitive)
warnings, namely that in the following sequence

  $ git checkout origin/master
  $ git status
  # On remote-tracking branch origin/master of remote origin
  # ...
Sure.
  $ git commit

'git commit' would refuse committing on non-heads ref, and propose,
beside _always_ proposing detaching HEAD and committing on such
detached HEAD (unnamed branch) via "git checkout HEAD^0", or
"git checkout --detach [HEAD]":
... or the current "this is not a local branch -- use checkout -b to 
create one" warning, just like what we have today when checking out a 
tag or remote branch, except that the warning is deferred to the commit 
operation which in fact might even not take place.
1. If there is no local branch which follows 'origin/master'
   (which has 'origin/master' as upstream, which tracks 'origin/master')
   propose creating it before comitting:

    $ git checkout -t origin/master

2. If there is single local branch that follows 'origin/master',
   and it fast-forwards to 'origin/master' propose... 
   errr, something that would mean fast-forwarding this branch
   and making a commit on local branch that has 'origin/master'
   as upstream.
   
3. If there is single local branch that follows 'origin/master', but
   it has changes / diverges from 'origin/master' we are viewing,
   propose... hmmm, what then?

4. If there are more than one local branch that has 'origin/master'
   as upstream, list all those branches in message.
I wouldn't go too far in that direction though.  Too many suggestions 
would simply bring back confusion to the new user who at that point 
might not even understand yet what all the different concepts are.


Nicolas

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Nicolas Pitre <nico@fluxnic.net>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, Daniel Barkalow wrote:
I think the description used in CVS and SVN (and, I think, others) is that 
you're not at the HEAD revision. I think they both account for the state 
where you've checked out the revision by number that's the latest 
revision, but you still can't grow the branch because you can't 
simultaneously stay on r1000 (as requested explicitly) and add a new 
commit.

So maybe the right explanation is:

$ git checkout master; git branch
* master
$ git checkout origin/master; git branch
* origin/master (not at head)
$ git checkout 123cafe^5; git branch
* 123cafe^5 (not at head)
I think this is wrong.  Git has multiple heads, and insisting on "not at 
head" would be extremely confusing.


Nicolas

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, Nicolas Pitre wrote:
On Thu, 15 Oct 2009, Daniel Barkalow wrote:
quoted
I think the description used in CVS and SVN (and, I think, others) is that 
you're not at the HEAD revision. I think they both account for the state 
where you've checked out the revision by number that's the latest 
revision, but you still can't grow the branch because you can't 
simultaneously stay on r1000 (as requested explicitly) and add a new 
commit.

So maybe the right explanation is:

$ git checkout master; git branch
* master
$ git checkout origin/master; git branch
* origin/master (not at head)
$ git checkout 123cafe^5; git branch
* 123cafe^5 (not at head)
I think this is wrong.  Git has multiple heads, and insisting on "not at 
head" would be extremely confusing.
Maybe "(not at a head)"? Git does have multiple heads, but what's checked 
out isn't one of them, and that's actually the point.

	-Daniel
*This .sig left intentionally blank*

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:47:33

On Thu, 15 Oct 2009, James Pickens wrote:
On Wed, Oct 14, 2009 at 4:09 PM, Jeff King [off-list ref] wrote:
quoted
That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

 $ git checkout --detach=commit origin/master
 $ git commit ;# should be ok

 $ git checkout --detach=examine origin/master
 $ git commit ;# complain
 $ git checkout --detach=commit HEAD
 $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain
 $ git checkout origin/master
 $ git fetch
 $ git checkout origin/next
 Uncommited file '...' would be overwritten.

If HEAD is a symref to refs/remotes/origin/master, and you update 
refs/remotes/origin/master, git will subsequently see that your index 
doesn't match HEAD, and when you switch branches, it will try to apply a 
revert to the branch you're switching to. It's the same issue as pushing 
into a non-bare repository.

	-Daniel
*This .sig left intentionally blank*

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Thomas Rast <hidden>
Date: 2016-06-15 22:47:33

Daniel Barkalow wrote:
On Thu, 15 Oct 2009, Nicolas Pitre wrote:
quoted
On Thu, 15 Oct 2009, Daniel Barkalow wrote:
quoted
I think the description used in CVS and SVN (and, I think, others) is that 
you're not at the HEAD revision.
[...]
quoted
quoted
* origin/master (not at head)
$ git checkout 123cafe^5; git branch
* 123cafe^5 (not at head)
I think this is wrong.  Git has multiple heads, and insisting on "not at 
head" would be extremely confusing.
Maybe "(not at a head)"? Git does have multiple heads, but what's checked 
out isn't one of them, and that's actually the point.
Please don't reuse 'head' (even lowercase) in this context/meaning.  I
see enough people coming to IRC who are confused about the fact that
they checked out some old commit, hence HEAD is just that, but they
refer to the *newest* commit on whatever branch they like most as HEAD
because that's what it means in SVN.

Now imagine having to explain to them that their (SVN) 'HEAD' is not
the same as git's 'HEAD', but can rightly be considered the equivalent
of master's 'head'; and that furthermore, you are always at 'HEAD' but
not always at 'head'.

I think in this case '(detached)' would be more consistent with
current terminology, though we may of course try to change it.

(I've tried to consistently use 'tip' in the branch tip meaning,
admittedly without knowing exactly how this intersects with
mercurial's definition of the term.)

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Julian Phillips <hidden>
Date: 2016-06-15 22:47:34

On Thu, 15 Oct 2009, Daniel Barkalow wrote:
On Thu, 15 Oct 2009, James Pickens wrote:
quoted
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain
$ git checkout origin/master
$ git fetch
$ git checkout origin/next
Uncommited file '...' would be overwritten.
How about:

$ git checkout origin/master
$ git fetch
Refusing to fetch, as it would update a checkedout branch
"git fetch -f" will force the update, but you will need to run "git 
reset --hard HEAD" to update your checkout to match.

?

-- 
Julian

  ---
    If you care, you just get disappointed all the time. If you don't care
nothing matters so you are never upset.	  -- Calvin

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Björn Steinbrink <hidden>
Date: 2016-06-15 22:47:34

On 2009.10.16 13:15:35 +0100, Julian Phillips wrote:
On Thu, 15 Oct 2009, Daniel Barkalow wrote:
quoted
On Thu, 15 Oct 2009, James Pickens wrote:
quoted
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain
$ git checkout origin/master
$ git fetch
$ git checkout origin/next
Uncommited file '...' would be overwritten.
How about:

$ git checkout origin/master
$ git fetch
Refusing to fetch, as it would update a checkedout branch
"git fetch -f" will force the update, but you will need to run "git
reset --hard HEAD" to update your checkout to match.
That would redefine -f (currently means "allow non-fast-forward
updates"), the flag that allows the checked out branch head to be
updated is -u, --update-head-ok, and is for internal use only.

And suggesting "reset --hard" seems wrong, that just kills any
uncommitted changes.

And such uncommitted changes would be lost in the big "undo the fetch
update" diff. So you'd have to do:
git reset --soft HEAD@{1}
git checkout --merge HEAD@{1}

to keep them, while updating to the new state of the remote tracking
branch. Not quite intuitive, is it?

Björn

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Julian Phillips <hidden>
Date: 2016-06-15 22:47:34

On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote:
On 2009.10.16 13:15:35 +0100, Julian Phillips wrote:
quoted
On Thu, 15 Oct 2009, Daniel Barkalow wrote:
quoted
On Thu, 15 Oct 2009, James Pickens wrote:
quoted
How about not detaching the head at all if the user checks out any ref, and
reject commits if he checked out a tag or remote branch.  For example:

$ git checkout origin/master
$ git status
# On branch origin/master
$ git commit ;# complain
$ git checkout origin/master
$ git fetch
$ git checkout origin/next
Uncommited file '...' would be overwritten.
How about:

$ git checkout origin/master
$ git fetch
Refusing to fetch, as it would update a checkedout branch
"git fetch -f" will force the update, but you will need to run "git
reset --hard HEAD" to update your checkout to match.
That would redefine -f (currently means "allow non-fast-forward
updates"), the flag that allows the checked out branch head to be
updated is -u, --update-head-ok, and is for internal use only.

And suggesting "reset --hard" seems wrong, that just kills any
uncommitted changes.
Ok, so the commands were wrong.  Not important.

It was the approach that I was trying to suggest rather than the actual 
commands.  The point I was trying to make was how, as a user, I would be 
happy to git behave.

So, I try to run fetch, git says "ooh, now that would be dangerous - you 
can force it happen by running "git foo", but you will then be in 
situation X, which you can then recover from by running "git bar", though 
you may need to run "git stash" to save any edits you have made" or 
something similar.

Now as a user I know that I have tried to do something a bit unusual, but 
I don't have to run to the mailing list or #git saying "I just did X Y Z 
and everything is now FUBARed".  I can even proceed to do the unusal 
thing, as git itself has given me the information I need to sort things 
out afterwards.
And such uncommitted changes would be lost in the big "undo the fetch
update" diff. So you'd have to do:
git reset --soft HEAD@{1}
git checkout --merge HEAD@{1}

to keep them, while updating to the new state of the remote tracking
branch. Not quite intuitive, is it?
I don't care what git has to do, I'm talking about the user experience - 
if we have to write some new code to support it, that really isn't a 
terribly hard thing to do.  UIs should be driven down from the user 
interaction not up from the implementation.

-- 
Julian

  ---
Captain: "Catalyzer's a nothing part, captain."

Mal: "It's nothing until you don't got one. Then it appears to be everything."
 				--Episode #8, "Out of Gas"

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:47:34

On Fri, 16 Oct 2009, Julian Phillips wrote:
It was the approach that I was trying to suggest rather than the actual
commands.  The point I was trying to make was how, as a user, I would be happy
to git behave.

So, I try to run fetch, git says "ooh, now that would be dangerous - you can
force it happen by running "git foo", but you will then be in situation X,
which you can then recover from by running "git bar", though you may need to
run "git stash" to save any edits you have made" or something similar.

Now as a user I know that I have tried to do something a bit unusual, but I
don't have to run to the mailing list or #git saying "I just did X Y Z and
everything is now FUBARed".  I can even proceed to do the unusal thing, as git
itself has given me the information I need to sort things out afterwards.
The thing is that that sequence shouldn't be unusual or dangerous or 
require sorting things out afterwards. In the current version of git, it's 
a completely normal thing to do that behaves nicely and does what the user 
almost certainly wants. We *could* horribly break it, and then add 
messages to tell the user they're doing something that's now horribly 
broken, and tell the user how to cope with the fact that what they want to 
do involves something that's horribly broken, and roll our eyes when users 
who have only used working systems like SVN or git 1.6.X ignore the 
message and can't figure out what's going on. Or we could just not break 
it in the first place.

SVN doesn't think that your working directory is supposed to change when 
someone else makes a commit. Git shouldn't think your working directory 
should change when you find out that someone made a commit. If you want to 
see now commits, you do "svn up" or "git checkout".

	-Daniel
*This .sig left intentionally blank*

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Björn Steinbrink <hidden>
Date: 2016-06-15 22:47:34

On 2009.10.16 18:31:23 +0100, Julian Phillips wrote:
On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote:
quoted
On 2009.10.16 13:15:35 +0100, Julian Phillips wrote:
quoted
How about:

$ git checkout origin/master
$ git fetch
Refusing to fetch, as it would update a checkedout branch
"git fetch -f" will force the update, but you will need to run "git
reset --hard HEAD" to update your checkout to match.
That would redefine -f (currently means "allow non-fast-forward
updates"), the flag that allows the checked out branch head to be
updated is -u, --update-head-ok, and is for internal use only.

And suggesting "reset --hard" seems wrong, that just kills any
uncommitted changes.
Ok, so the commands were wrong.  Not important.

It was the approach that I was trying to suggest rather than the
actual commands.  The point I was trying to make was how, as a user,
I would be happy to git behave.
Your approach explicitly included "mess up the index/worktree state",
otherwise, "git fetch" would not have to tell the user that he has to do
a "git reset --hard HEAD". I honestly can't believe that you would be
happy with git messing up your work.
So, I try to run fetch, git says "ooh, now that would be dangerous -
you can force it happen by running "git foo", but you will then be
in situation X, which you can then recover from by running "git
bar", though you may need to run "git stash" to save any edits you
have made" or something similar.
But why make "git fetch" with non-"obscure" refspecs dangerous to begin
with? If we detach but keep some extra information, there's no need to
make "git fetch" dangerous, _and_ we can still provide a command that
just fetches the most recent version of the "checked out" remote
tracking branch and checks that out. May it be another mode of operation
for "git pull" or some "git up" command or whatever.
quoted
And such uncommitted changes would be lost in the big "undo the fetch
update" diff. So you'd have to do:
git reset --soft HEAD@{1}
git checkout --merge HEAD@{1}

to keep them, while updating to the new state of the remote tracking
branch. Not quite intuitive, is it?
I don't care what git has to do, I'm talking about the user
experience - if we have to write some new code to support it, that
really isn't a terribly hard thing to do.  UIs should be driven down
from the user interaction not up from the implementation.
Those commands are those that git would have to show to you, instead of
"git reset --hard HEAD", i.e. they're what you, as the user, have to do.
And while "git reset --hard HEAD" might be remotely understandable to
the user, that command sequence is very unlikely to be understood by
most. And providing a command that does just this sequence is insane,
it's just a bandaid for git doing crap to your worktree/index state. So
let's better not start with git doing that crap at all.

My current "idea" (I don't think I'll have time to implement that any
time soon) is:

Keep some extra information in HEAD (or somewhere else) when HEAD is
detached about the ref that HEAD is "weakly" bound to. For example, "git
checkout origin/master" might create a weak binding to
refs/remotes/origin/master (for other [corner] cases, see the other
mail I wrote, in which I outlined some cases I considered interesting).

"git update" can use the branch.<name>.{remote,merge} setup, or
alternatively the "weak binding" information, to fetch from the right
remote, and checks whether a fast-forward of HEAD to the according
upstream branch head is possible. If so, it does a "git checkout --merge
<upstream>" (possibly leaving conflicts for the uncommitted changes,
just like "svn update"). If a fast-forward is not possible, it
complains, telling the user that he needs to use "git merge/rebase/pull"
instead, and might want to create a branch head, in case of a detached
HEAD.

If there's also going to be a rule that forbids commits on some kind of
detached HEAD, than the command could also tell the user (when a
fast-forward is not possible) that upstream possibly rewrote history,
and that the user might want to use "git checkout --merge <upstream>"
(or maybe "git update -f"?) to just go to the new upstream version (not
sure if that hint should be shown in addition to or instead of the "git
merge/rebase/pull" hint).

Björn

Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was

From: Julian Phillips <hidden>
Date: 2016-06-15 22:47:34

On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:
On 2009.10.16 18:31:23 +0100, Julian Phillips wrote:
quoted
On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote:
quoted
On 2009.10.16 13:15:35 +0100, Julian Phillips wrote:
quoted
How about:

$ git checkout origin/master
$ git fetch
Refusing to fetch, as it would update a checkedout branch
"git fetch -f" will force the update, but you will need to run "git
reset --hard HEAD" to update your checkout to match.
That would redefine -f (currently means "allow non-fast-forward
updates"), the flag that allows the checked out branch head to be
updated is -u, --update-head-ok, and is for internal use only.

And suggesting "reset --hard" seems wrong, that just kills any
uncommitted changes.
Ok, so the commands were wrong.  Not important.

It was the approach that I was trying to suggest rather than the
actual commands.  The point I was trying to make was how, as a user,
I would be happy to git behave.
Your approach explicitly included "mess up the index/worktree state",
otherwise, "git fetch" would not have to tell the user that he has to do
a "git reset --hard HEAD". I honestly can't believe that you would be
happy with git messing up your work.
quoted
So, I try to run fetch, git says "ooh, now that would be dangerous -
you can force it happen by running "git foo", but you will then be
in situation X, which you can then recover from by running "git
bar", though you may need to run "git stash" to save any edits you
have made" or something similar.
But why make "git fetch" with non-"obscure" refspecs dangerous to begin
with? If we detach but keep some extra information, there's no need to
make "git fetch" dangerous, _and_ we can still provide a command that
just fetches the most recent version of the "checked out" remote
tracking branch and checks that out. May it be another mode of operation
for "git pull" or some "git up" command or whatever.
My entire argument was in the context of the mail that I orginally replied 
to, i.e. assuming that the decision to not detach had been taken.  If that 
is not the case, then everything I had said is irrelevant.

I wasn't arguing against detaching, but rather trying to say that _if_ we 
are not going to detach then I think it would better like this than that. 
I don't personally have any input on the detach or not, as I have been 
using git for too long to know if detaching is a problem for others.  I 
can tell from my bash prompt if I'm detached or on a branch - and that's 
fine for me.

-- 
Julian

  ---
Wedding is destiny, and hanging likewise.
 		-- John Heywood
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help