Re: disallowing push to currently checked-out branch
From: Jeff King <hidden>
Date: 2016-06-15 22:46:13
On Mon, Feb 16, 2009 at 01:43:03PM -0800, Junio C Hamano wrote:
Sergio Callegari [off-list ref] writes:quoted
... is there some case where one wants and has reasons to commit to a detached head before making a temporary branch on it?Absolutely. I do it all the time for minor fix-ups after applying other's patches on a newly created topic branch.
This question got me thinking. At the time that detached HEAD was
introduced, I argued for a loud warning message, claiming that for most
users, commiting on a detached HEAD was dangerous and unintentional and
there _should_ be a big warning message. And like then, committing on a
detached HEAD is still not something I generally do.
But then I realized there is actually one time: during interactive
rebase, which detaches HEAD during the rebase processs, and then puts
the final detached value back into the branch ref for you (or not, if
you abort).
Which made me think how such a process interacts with pushing into a
non-bare repo. If we are detached, the push cannot, by definition, touch
the ref pointed to by HEAD, since ther isn't one. But there is still
some sense of "current branch" recorded by rebase; after the rebase is
completed, it attempts to put a new value in the ref.
So this is still some conflict possible even with the current safety
valves. Fortunately, the ref update is smart enough to realize the value
has changed behind our back:
$ git rebase --continue
error: Ref refs/heads/master is at 5836aa51b217a1c88f32107cbcd606bece018657 but expected d2d7bf3fcaa927ef997dbcdaf9d9a9e176d6a8d0
fatal: Cannot lock the ref 'refs/heads/master'.
But that doesn't give any hint to the user about what happened, or how
to fix it.
So:
1. How can we improve this situation?
One option is including "the branch we are rebasing on" in the list
of refs to deny. I don't like that, though, because that becomes an
ever-growing list of places for receive-pack to look, some of which
are not even part of core git.
I think the best bet is just detecting the situation (which we
already do) and giving a sane recipe for resolution. Probably
something like:
git branch incoming master ;# stash newly pushed changes
git branch -f master $old_sha1 ;# restore previous state
git rebase --continue ;# finish the rebase
git merge incoming ;# pull in the pushed changes
2. Are there other "we are implicitly assuming $ref won't change
behind our backs" long-term commands?
-Peff