About detached heads

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

About detached heads

From: Geoff Russell <hidden>
Date: 2016-06-15 22:44:23

This should be simple! I have a series of commits:

           1---2---3---4---5

I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3

?

         git checkout 3...

gets me the commit on a detached head, but I don't know how to put this back
as the HEAD.

I'm on git 1.5.0.5

Cheers,
Geoff Russell

Re: About detached heads

From: Jonathan del Strother <hidden>
Date: 2016-06-15 22:44:23

On Fri, Mar 14, 2008 at 9:46 AM, Geoff Russell
[off-list ref] wrote:
This should be simple! I have a series of commits:

           1---2---3---4---5

 I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3

 ?

         git checkout 3...

 gets me the commit on a detached head, but I don't know how to put this back
 as the HEAD.

Two options.  Either rewrite history, nuking commits 4 & 5 :
  git reset --hard 3

or publicly reverse the changes introduced by 5 & 4 :
  git revert 5
  git revert 4

Jon

Re: About detached heads

From: Wincent Colaiuta <hidden>
Date: 2016-06-15 22:44:23

El 14/3/2008, a las 10:46, Geoff Russell escribió:
This should be simple! I have a series of commits:

          1---2---3---4---5

I want to go back to 3 but not branch, so I want

          1---2---3---4---5---3

?

        git checkout 3...

gets me the commit on a detached head, but I don't know how to put  
this back
as the HEAD.

I'm on git 1.5.0.5
How about?

   git cherry-pick the-sha-1-id-of-commit-3

Wincent

Re: About detached heads

From: David Kågedal <hidden>
Date: 2016-06-15 22:44:23

"Jonathan del Strother" [off-list ref] writes:
On Fri, Mar 14, 2008 at 9:46 AM, Geoff Russell
[off-list ref] wrote:
quoted
This should be simple! I have a series of commits:

           1---2---3---4---5

 I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3

 ?

         git checkout 3...

 gets me the commit on a detached head, but I don't know how to put this back
 as the HEAD.

Two options.  Either rewrite history, nuking commits 4 & 5 :
  git reset --hard 3

or publicly reverse the changes introduced by 5 & 4 :
  git revert 5
  git revert 4
The revert can be done by resetting to the tree in 3:

  git checkout 3 -- .
  git commit -m "reset to 3"

-- 
David Kågedal

Re: About detached heads

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:44:23

"Geoff Russell" [off-list ref] writes:
This should be simple! I have a series of commits:

           1---2---3---4---5

I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3

?

         git checkout 3...

gets me the commit on a detached head, but I don't know how to put this back
as the HEAD.
Lets check what git does in each of scenarios. Let's assume that
current branch is named 'master'.

At beginning we have:

   1---2---3---4---5    <--- master <--- HEAD

HEAD contents is "ref: refs/heads/master"

1. Now, "git checkout 3...", which is equivalent to "git checkout 3",
detaches HEAD because commit '3' is not a head (is not a branch), so
we have:

   1---2---3---4---5    <--- master
           ^
            \ 
             \-------------- HEAD

HEAD contents is "<sha1 of 3>"


2. If we did "git reset --hard 3" we would rewind the history,
resulting in the following situation:

   1---2---3           <--- master <--- HEAD
            \           
             \-4---5   <... master@{1}, ORIG_HEAD, HEAD@{1}
              
and now commits 4 and 5 are referenced only by reflogs, and by the
(temporary) "last position of HEAD" reference named ORIG_HEAD.


3. Now, if you have published 1..5 history you would not want
(usually) to rewind published branch. If you do the following:

  $ git revert --no-commit 5
  $ git revert 4

you would get the following:

   1---2---3---4---5---(5^-1 4^-1 => 3)  <--- master <--- HEAD

git-revert applies reversal of changes in given commit, in the 
"patch -R" ("patch --reverse") sense. Using '--no-commit' option
allows to squash reverting two commits into one commit. The ordering
of reverting ensures that there are no merge conflicts.


4. Or you can just put the _contents_ of revision 3 into your working
tree, either using plumbing command git-read-tree, or by checking out
or resetting to top tree: "git checkout 3^{tree}", or 
"git checkout 3 -- .", or equivalent git-reset invocation.

This way you would get exactly

   1---2---3---4---5---3   <--- master <--- HEAD

but the relation of 5---3 parentage is unclear: you would have to
explain it in the commit mesage.

HTH
-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: About detached heads

From: Adam Piatyszek <hidden>
Date: 2016-06-15 22:44:23

* Jakub Narebski [14 III 2008 11:52]:
 > Lets check what git does in each of scenarios. Let's assume that
 > current branch is named 'master'.
 >
 > At beginning we have:
 >
 >    1---2---3---4---5    <--- master <--- HEAD
 >
 > HEAD contents is "ref: refs/heads/master"
 >
 > 1. Now, "git checkout 3...", which is equivalent to "git checkout 3",
 > detaches HEAD because commit '3' is not a head (is not a branch), so
 > we have:
 >
 >    1---2---3---4---5    <--- master
 >            ^
 >             \
 >              \-------------- HEAD
 >
 > HEAD contents is "<sha1 of 3>"
 >
 >
 > 2. If we did "git reset --hard 3" we would rewind the history,
 > resulting in the following situation:
 >
 >    1---2---3           <--- master <--- HEAD
 >             \
 >              \-4---5   <... master@{1}, ORIG_HEAD, HEAD@{1}
 >
 > and now commits 4 and 5 are referenced only by reflogs, and by the
 > (temporary) "last position of HEAD" reference named ORIG_HEAD.
 >
 >
 > 3. Now, if you have published 1..5 history you would not want
 > (usually) to rewind published branch. If you do the following:
 >
 >   $ git revert --no-commit 5
 >   $ git revert 4
 >
 > you would get the following:
 >
 >    1---2---3---4---5---(5^-1 4^-1 => 3)  <--- master <--- HEAD
 >
 > git-revert applies reversal of changes in given commit, in the
 > "patch -R" ("patch --reverse") sense. Using '--no-commit' option
 > allows to squash reverting two commits into one commit. The ordering
 > of reverting ensures that there are no merge conflicts.
 >
 >
 > 4. Or you can just put the _contents_ of revision 3 into your working
 > tree, either using plumbing command git-read-tree, or by checking out
 > or resetting to top tree: "git checkout 3^{tree}", or
 > "git checkout 3 -- .", or equivalent git-reset invocation.
 >
 > This way you would get exactly
 >
 >    1---2---3---4---5---3   <--- master <--- HEAD
 >
 > but the relation of 5---3 parentage is unclear: you would have to
 > explain it in the commit mesage.

I suggest one should add the above nice explanation to FAQ or some wiki 
material.

BR,
/Adam

-- 
.:.  Adam Piatyszek (ediap)  .:.....................................:.
.:.  ediap@users.sourceforge.net  .:................................:.

Re: About detached heads

From: Chris Shoemaker <hidden>
Date: 2016-06-15 22:44:23

On Fri, Mar 14, 2008 at 03:52:14AM -0700, Jakub Narebski wrote:
"Geoff Russell" [off-list ref] writes:
quoted
This should be simple! I have a series of commits:

           1---2---3---4---5

I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3

?

         git checkout 3...

gets me the commit on a detached head, but I don't know how to put this back
as the HEAD.
Lets check what git does in each of scenarios. Let's assume that
current branch is named 'master'.

At beginning we have:

   1---2---3---4---5    <--- master <--- HEAD

HEAD contents is "ref: refs/heads/master"

1. Now, "git checkout 3...", which is equivalent to "git checkout 3",
detaches HEAD because commit '3' is not a head (is not a branch), so
we have:

   1---2---3---4---5    <--- master
           ^
            \ 
             \-------------- HEAD

HEAD contents is "<sha1 of 3>"


2. If we did "git reset --hard 3" we would rewind the history,
resulting in the following situation:

   1---2---3           <--- master <--- HEAD
            \           
             \-4---5   <... master@{1}, ORIG_HEAD, HEAD@{1}
              
and now commits 4 and 5 are referenced only by reflogs, and by the
(temporary) "last position of HEAD" reference named ORIG_HEAD.


3. Now, if you have published 1..5 history you would not want
(usually) to rewind published branch. If you do the following:

  $ git revert --no-commit 5
  $ git revert 4

you would get the following:

   1---2---3---4---5---(5^-1 4^-1 => 3)  <--- master <--- HEAD

git-revert applies reversal of changes in given commit, in the 
"patch -R" ("patch --reverse") sense. Using '--no-commit' option
allows to squash reverting two commits into one commit. The ordering
of reverting ensures that there are no merge conflicts.


4. Or you can just put the _contents_ of revision 3 into your working
tree, either using plumbing command git-read-tree, or by checking out
or resetting to top tree: "git checkout 3^{tree}", or 
"git checkout 3 -- .", or equivalent git-reset invocation.

This way you would get exactly

   1---2---3---4---5---3   <--- master <--- HEAD

but the relation of 5---3 parentage is unclear: you would have to
explain it in the commit mesage.
[Great explanation.  Let me offer one minor clarification:]

 This way you would get exactly:
 
    1---2---3---4---5---3'   <--- master <--- HEAD
 
 While the 3' commit has the same contents as 3, it is a new, distinct
 commit with its own history.  Its commit message should explain why
 you want to go from 5 back to the contents of 3.

-chris

Re: About detached heads

From: Rafael Garcia-Suarez <hidden>
Date: 2016-06-15 22:44:23

On 14/03/2008, Chris Shoemaker wrote:
  This way you would get exactly:

    1---2---3---4---5---3'   <--- master <--- HEAD


 While the 3' commit has the same contents as 3, it is a new, distinct
  commit with its own history.  Its commit message should explain why
  you want to go from 5 back to the contents of 3.
Just a small question -- does that mean that 3 and 3' share the same
tree object ?

Re: About detached heads

From: Nicolas Pitre <hidden>
Date: 2016-06-15 22:44:23

On Fri, 14 Mar 2008, Rafael Garcia-Suarez wrote:
On 14/03/2008, Chris Shoemaker wrote:
quoted
  This way you would get exactly:

    1---2---3---4---5---3'   <--- master <--- HEAD


 While the 3' commit has the same contents as 3, it is a new, distinct
  commit with its own history.  Its commit message should explain why
  you want to go from 5 back to the contents of 3.
Just a small question -- does that mean that 3 and 3' share the same
tree object ?
Yes.  However, they don't share the same parent in the commit object, so 
even if the commit text was the same and the time stamps were forced to 
be the same, the commit 3' won't have the same SHA1.


Nicolas

Re: About detached heads

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:44:23

On Fri, 14 Mar 2008, Rafael Garcia-Suarez wrote:
On 14/03/2008, Chris Shoemaker wrote:
quoted
  This way you would get exactly:

    1---2---3---4---5---3'   <--- master <--- HEAD


 While the 3' commit has the same contents as 3, it is a new, distinct
  commit with its own history.  Its commit message should explain why
  you want to go from 5 back to the contents of 3.
Just a small question -- does that mean that 3 and 3' share the same
tree object ?
Yes it does. 

Commit object has link to a tree object in the form
of its sha1 id, and repository's object store is content addressed,
or to be more exact sha-1 id of contents addressed.

-- 
Jakub Narebski
Poland

Re: About detached heads

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:44:23


On Fri, 14 Mar 2008, Geoff Russell wrote:
This should be simple! I have a series of commits:

           1---2---3---4---5

I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3
This is actually an uncommonly easy operation for core git, but it's a 
very unusual thing to want to do in general, so I don't think there is any 
high-level command to do it directly. But it's really easy to do with 
a single so-called "plumbing" command, namely "git read-tree".

So the "core git" way to do it is to literally just do

	git read-tree -u -m 3
	git commit

(or use "--reset" instead of "-m" if you want to do it even in the 
presense unmerged entries).

What the above does is to literally just read the tree state at "3", and 
make it the new index: the "-u" means that we also want to update the 
working tree to that state, and the "-m" means that we will merge in the 
old index stat information.

The commit then will then create the actual new commit: it will have the 
exact same tree as your commit '3', but it will be a new commit (so call 
it 3').

Of course, people have already pointed out that another easy way to do it 
is to just revert 5 and 4. That may be the more high-level way to do it, 
but the git-read-tree approach actually has the advantage that it will 
work even across merges etc, and it will be very unambiguous: we want 
*exactly* the state at commit 3 back, nothing else.

			Linus

Re: About detached heads

From: Björn Steinbrink <hidden>
Date: 2016-06-15 22:44:23

On 2008.03.14 10:53:25 -0700, Linus Torvalds wrote:

On Fri, 14 Mar 2008, Geoff Russell wrote:
quoted
This should be simple! I have a series of commits:

           1---2---3---4---5

I want to go back to 3 but not branch, so I want

           1---2---3---4---5---3
This is actually an uncommonly easy operation for core git, but it's a 
very unusual thing to want to do in general, so I don't think there is any 
high-level command to do it directly. But it's really easy to do with 
a single so-called "plumbing" command, namely "git read-tree".

So the "core git" way to do it is to literally just do

	git read-tree -u -m 3
	git commit

(or use "--reset" instead of "-m" if you want to do it even in the 
presense unmerged entries).

What the above does is to literally just read the tree state at "3", and 
make it the new index: the "-u" means that we also want to update the 
working tree to that state, and the "-m" means that we will merge in the 
old index stat information.

The commit then will then create the actual new commit: it will have the 
exact same tree as your commit '3', but it will be a new commit (so call 
it 3').

Of course, people have already pointed out that another easy way to do it 
is to just revert 5 and 4. That may be the more high-level way to do it, 
but the git-read-tree approach actually has the advantage that it will 
work even across merges etc, and it will be very unambiguous: we want 
*exactly* the state at commit 3 back, nothing else.
Hm, that's just squashing revert commit. Squashing can be done via:
git reset --soft HEAD~5    # Or wherever your squashed commit should start
git commit -m "Squashed from HEAD~5 onwards"

Now the "revert" version of that:
git reset --hard HEAD~5      # Go back to the state that we want
git reset --soft ORIG_HEAD   # Move HEAD back, but keep the index as is
git commit -m "Back at the state of HEAD~5"

AFAICT that should have the same advantages as using read-tree, but
doesn't feel so low-level :-)

Björn

Re: About detached heads

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:44:23


On Fri, 14 Mar 2008, Bj?rn Steinbrink wrote:
Hm, that's just squashing revert commit. Squashing can be done via:
git reset --soft HEAD~5    # Or wherever your squashed commit should start
git commit -m "Squashed from HEAD~5 onwards"

Now the "revert" version of that:
git reset --hard HEAD~5      # Go back to the state that we want
git reset --soft ORIG_HEAD   # Move HEAD back, but keep the index as is
git commit -m "Back at the state of HEAD~5"

AFAICT that should have the same advantages as using read-tree, but
doesn't feel so low-level :-)
Umm. The low-level one is a *lot* easier to understand than your 
"high-level" one, wouldn't you say?

And when the low-level plumbing commands are easier, are they not then 
better porcelain?

		Linus

Re: About detached heads

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:44:23

Linus Torvalds [off-list ref] writes:
On Fri, 14 Mar 2008, Bjorn Steinbrink wrote:
quoted
On 2008.03.14 10:53:25 -0700, Linus Torvalds wrote:
quoted
So the "core git" way to do it is to literally just do

	git read-tree -u -m 3
	git commit

(or use "--reset" instead of "-m" if you want to do it even in the 
presense unmerged entries).
Hm, that's just squashing revert commit. Squashing can be done via:
git reset --soft HEAD~5    # Or wherever your squashed commit should start
git commit -m "Squashed from HEAD~5 onwards"

Now the "revert" version of that:
git reset --hard HEAD~5      # Go back to the state that we want
git reset --soft ORIG_HEAD   # Move HEAD back, but keep the index as is
git commit -m "Back at the state of HEAD~5"

AFAICT that should have the same advantages as using read-tree, but
doesn't feel so low-level :-)
Umm. The low-level one is a *lot* easier to understand than your 
"high-level" one, wouldn't you say?

And when the low-level plumbing commands are easier, are they not then 
better porcelain?
AFAIK the porcelain equivalent to plumbing

  git read-tree -u -m 3

is just

  git checkout 3 -- .

-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: About detached heads

From: Sean <hidden>
Date: 2016-06-15 22:44:23

On Fri, 14 Mar 2008 12:11:33 -0700 (PDT)
Jakub Narebski [off-list ref] wrote:
AFAIK the porcelain equivalent to plumbing

  git read-tree -u -m 3

is just

  git checkout 3 -- .
Hi Jakub,

   git checkout .   won't remove paths, so you could end up with extra
state that didn't exist in the earlier commit.

Sean

Re: About detached heads

From: Geoff Russell <hidden>
Date: 2016-06-15 22:44:23

I thought my question was trivial, but judging by the number of answers, clearly
not!

I understand "git read-tree -u -m 3 ; git commit" and it does exactly
what I want.

The context where I want to use this is for users who update files,
can understand
"take me back to the state I was in at 4pm yesterday before I mucked up
my data" but who don't want to know about merging, branching, topics, etc, etc,
But of course having taken them back to the 4pm commit, they then realise that
they really need the 6pm commit or perhaps the 3pm commit. So anything which
just throws away commits would be risky.

The "git read-tree -u -m 3; git commit" allows me to present a simple
straight line
view of the data, which is perfect for the people I'm dealing with.

Many thanks to you all,

Cheers,
Geoff Russell

Re: About detached heads

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:44:23

"Geoff Russell" [off-list ref] writes:
I thought my question was trivial, but judging by the number of
answers, clearly not!

I understand "git read-tree -u -m 3 ; git commit" and it does exactly
what I want.

The context where I want to use this is for users who update files,
can understand "take me back to the state I was in at 4pm yesterday
before I mucked up my data" but who don't want to know about
merging, branching, topics, etc, etc, But of course having taken
them back to the 4pm commit, they then realise that they really need
the 6pm commit or perhaps the 3pm commit. So anything which just
throws away commits would be risky.
Thanks to the reflog even if they go the "git reset --hard 3" route,
the commits would be protected for gc.reflogExpireUnreachable period,
which defaults to 30 days, by reflog. After this period they could be
garbage-collected.
The "git read-tree -u -m 3; git commit" allows me to present a
simple straight line view of the data, which is perfect for the
people I'm dealing with.
Simple, straight line with _rewinds_, i.e. not so simple history.

Unless you can expect users to find errors later than 30 days, or you
have pushed non-rewritable branch already, then "git reset --hard 3"
is IMHO a beter solution than "git read-file -u -m 3 && git commit -a".

-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: About detached heads

From: Nicolas Pitre <hidden>
Date: 2016-06-15 22:44:23

On Sat, 15 Mar 2008, Geoff Russell wrote:
The context where I want to use this is for users who update files,
can understand
"take me back to the state I was in at 4pm yesterday before I mucked up
my data" but who don't want to know about merging, branching, topics, etc, etc,
But of course having taken them back to the 4pm commit, they then realise that
they really need the 6pm commit or perhaps the 3pm commit. So anything which
just throws away commits would be risky.
The reflog can help you there as well.  You can simply do:

	git reset --hard HEAD@{yesterday.at.4pm}

and it'll magically bring you back to the state you were yesterday at 
4pm.  You need the 6pm state instead?  No problem: just ask for 
yesterday.at.6pm then.

And before doing the 'reset --hard', you might want to do a simple 
'checkout' beforehand so you can be sure it actually corresponds to what 
you want:

	git checkout HEAD@{yesterday.at.4pm}
	[compile, test, whatever]
	git checkout HEAD@{yesterday.at.6pm}
	[compile, test, whatever]

and when OK with it, then:

	# return to your master branch (or any other branch)
	git checkout master
	# then reset it to the desired state
	git reset --hard HEAD@{yesterday.at.6pm}


Nicolas

Re: About detached heads

From: Geoff Russell <hidden>
Date: 2016-06-15 22:44:23

On 3/15/08, Nicolas Pitre [off-list ref] wrote:
...

        git reset --hard HEAD@{yesterday.at.4pm}

 and it'll magically bring you back to the state you were yesterday at
 4pm.  You need the 6pm state instead?  No problem: just ask for
 yesterday.at.6pm then.

 And before doing the 'reset --hard', you might want to do a simple
 'checkout' beforehand so you can be sure it actually corresponds to what
 you want:

        git checkout HEAD@{yesterday.at.4pm}
        [compile, test, whatever]
        git checkout HEAD@{yesterday.at.6pm}
        [compile, test, whatever]

 and when OK with it, then:

        # return to your master branch (or any other branch)
        git checkout master
        # then reset it to the desired state
        git reset --hard HEAD@{yesterday.at.6pm}



 Nicolas
More useful advice ... many thanks.

Cheers,
Geoff.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help