Re: [git-users] How to recover from a "Detached Head"

2014-10-31 Thread Konstantin Khomoutov
On Wed, 29 Oct 2014 23:41:42 -0700 (PDT)
Anthony Berglas  wrote:

> I am trying to do something really simple.  I want to commit local
> changes to a remote repository.  But along the way other developers
> modified the remote.  This appears to be very difficult to do in Git.
> 
> When I finished my changes I did a commit -a.  All good.
> 
> But then the push failed.

At that point, you should have stopped and reached for the goto Git guy
in your enterprise ;-)

The major design principle of Git is that it's a distributed VCS (DVCS).
With this in mind, you should understand that the repository you were
trying to push to is somehow special only by policy ("it's a central
repository for our project Foo everyone uses to collaborate") but it's
not in any way special to Git on either side of the wire.
This is the reason why pushes don't work like in Subversion: the latter
is a client-server system, where commits ever happen and are stored on
the server.

Note that this feature of Subversion you're lamenting actually allows
to create commits of the state which did not ever exist on any of the
clients.  No, really, suppose Alice changes foo.cpp then commits, while
Bob is changing bar.cpp seeing an old state of foo.cpp in his working
directory.  Then Bob commits his changes, and Subversion happily
records this commit even though Bob's changes will surely break with
what Alice committed.

Git, as other DVCSes, won't allow this--the history which is pushed
somewhere must have two crucial properties:
* It must represent the complete state of the project (you can't commit
  changes in just a bunch of files).
* It must descent from the line of history already there (that is, if
  you're trying to push commit D to a branch "master" in a remote
  repository, and that branch currently "ends" with commit B, your D
  has to descend from that B--one way of the other, for instance,
  it's OK to push ...B->C->D but not ...A->C->D).

That's why Git failed your push: it required you to reconcile your
local changes with the changes used to update the target branch in the
remote repository with some other changes you did not see yet.

There are two ways to do that: merging and rebasing.  Both are done
after (or along with) fetching.  What to use depends on the workflow
accepted by your team and the concrete situation at hand.

> git fetch ok.

That was a sensible thing to do.

> So I tried to checkout the origin/master.

...and that wasn't.

origin/master is a so-called "remote branch" or "remote-tracking
branch".  Remote braches are sort of bookmarks which show you which
were the state of branches in a particular remote repository last time
you fetched from it--in this case, the branch "master" in the repository
known locally as "origin".  These branches are not "yours" and thus you
never work on them--they're only for reference.

These are explained well in, say, Pro Git.  My stab at explaining them
on this list is [1].

> That gave me a "detached head", even though it looked like I was on
> head.

Being in a state with detached HEAD means that the HEAD reference which
always points to a state on which the index and the work tree are
currently based is currently pointing at a specific commit rather than
to the tip of some branch.  The difference is that when HEAD points to
the tip of a branch, recording a new commit moves that brach's tip to
that new commit while committing on a detached HEAD merely updates that
HEAD reference and nothing else.

Git moves the repository to this state when you're checking out
something which is not a (normal local) branch--say, a tag, a specific
commit or, as in your case, a remote branch.  The reason is simple:
when you check out a thing like those just enumerated, you don't have a
branch to update with the commits to be recorded.

For some reason, working on detached HEAD is considered an "ace"
practice while there is really nothing special if you clearly
understand the mechanics.  Seasoned Git users routinely go into that
state to try out "crazy ideas"--there's little sense in trying to come
up with a name for a temporary branch to work on when you can just
start working and only *if* it turns out to be useful do something with
these new commits--say, assign a branch to them or tag them.

> It said create a branch so I created abtmp (I do not actually want
> any branches).

Yes, the situation just started to get more confusing.

In fact, Git merely suggested you might want to create a branch, not
said you had to.  The whole reason is that, while being in a detached
HEAD state, you check out some other state, the work done in that state
is sort of lost (not really) but getting hold on it requires some
knowledge not available from most Git crash courses.

> Then merged origin/master back into abtmp (which seems
> the wrong way).

It depends.  You can trivially recover from merging into "a wrong
branch", as explained below, what follows is an explanation of which
side of the merge to pick, and wh

[git-users] How to recover from a "Detached Head"

2014-10-30 Thread Anthony Berglas
Hello All,

I am trying to do something really simple.  I want to commit local changes 
to a remote repository.  But along the way other developers modified the 
remote.  This appears to be very difficult to do in Git.

When I finished my changes I did a commit -a.  All good.

But then the push failed.  git fetch ok.  So I tried to checkout the 
origin/master.  That gave me a "detached head", even though it looked like 
I was on head.  It said create a branch so I created abtmp (I do not 
actually want any branches).  Then merged origin/master back into abtmp 
(which seems the wrong way).

So now I have the following.  What I want is to get rid of abtmp and commit 
back to origin/master on the remote server.

$ git log --oneline --decorate --graph --all
*   5e0fcfb (HEAD, abtmp) Merge remote branch 'origin/master' into abtmp
|\  
| * 944773a (origin/master, origin/HEAD) - shrm has to be optional 
logically (if s
| * 4952f9c - correct to point by default
* | 75b9d6d (master)  Performace tests
|/  
* c1106db - replace with st
* b046367 - set back further
* 5a3ce83 - fixup doc link reference
* 2ca8ecf (tag: 7.0e) - this 

Questions:-

   1. How do I fix this up.
   2. What is the best way to deal with these simple conflicts in future.

Is there any doc that goes over this clearly. (e.g. not 
http://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes which goes 
over setting up multiple remotes etc. and other cleverness but not the 
basics.)

What is wanted is "How to use Git like Svn".

Thanks,

Anthony

-- 
You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to git-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.