Re: disallowing push to currently checked-out branch

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

Re: disallowing push to currently checked-out branch

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:12

Daniel Barkalow [off-list ref] writes:
In fact, if you expect to be pushing to a non-bare repository, you
probably want to have HEAD contain the actual commit currently checked
out (instead of a reference to externally mutable storage), which you
can do with "git checkout refs/heads/master".
"git checkout master^0" is shorter ;-)

For people who do not follow the git list regularly, a "HEAD contain the
actual commit" is often called "detached".

Re: disallowing push to currently checked-out branch

From: Sergio Callegari <hidden>
Date: 2016-06-15 22:46:12

Junio C Hamano <gitster <at> pobox.com> writes:
Daniel Barkalow <barkalow <at> iabervon.org> writes:
quoted
In fact, if you expect to be pushing to a non-bare repository, you
probably want to have HEAD contain the actual commit currently checked
out (instead of a reference to externally mutable storage), which you
can do with "git checkout refs/heads/master".
"git checkout master^0" is shorter 

For people who do not follow the git list regularly, a "HEAD contain the
actual commit" is often called "detached".

Could you have that done automatically?
Namely rather to denying push to a branch b where HEAD->b, when you get such
push you detach head?

Re: disallowing push to currently checked-out branch

From: Jeff King <hidden>
Date: 2016-06-15 22:46:12

On Mon, Feb 16, 2009 at 10:17:01AM +0000, Sergio Callegari wrote:
quoted
For people who do not follow the git list regularly, a "HEAD contain the
actual commit" is often called "detached".
Could you have that done automatically?
Namely rather to denying push to a branch b where HEAD->b, when you get such
push you detach head?
See

  http://article.gmane.org/gmane.comp.version-control.git/108923

for discussion.

-Peff

Re: disallowing push to currently checked-out branch

From: Sergio Callegari <hidden>
Date: 2016-06-15 22:46:12

Jeff King wrote:
On Mon, Feb 16, 2009 at 10:17:01AM +0000, Sergio Callegari wrote:

  
quoted
quoted
For people who do not follow the git list regularly, a "HEAD contain the
actual commit" is often called "detached".
      
Could you have that done automatically?
Namely rather to denying push to a branch b where HEAD->b, when you get such
push you detach head?
    
See

  http://article.gmane.org/gmane.comp.version-control.git/108923

for discussion.

-Peff
  
Thanks for the pointer!

However, wrt point 1)
If you set 'detach' option, this clueless user is not helped; he will
     happily keep working and would make tons of commits on detached HEAD,
     and next time he switches to another branch, will lose all of them.
  
I guess that git does not let you commit on a detached head without 
crying out loud.

Furthermore, one could do just a bit more than detaching, namely store 
the fact that head got detached and the name of the branch where the 
head was.
With this, when the unconscious user types git status or git commit the 
system could alert him that head got detached because someone updated 
the branch behind his shoulders from remote... and then suggest the 
option to either create a new branch from the detached head (I believe 
that this is what gets suggested anyway when one tries to commit from a 
detached head) or to stash the current tree status, get back onto the 
former branch and try applying the changes on the new head of the branch.
The flag triggering this warning at a git status or git commit command 
should then be cleared at the first occasion when the head is changed.

To me this seems natural and helpful. Am I missing something?

Sergio

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:12

Hi,

On Mon, 16 Feb 2009, Sergio Callegari wrote:
Jeff King wrote:
quoted
If you set 'detach' option, this clueless user is not helped; he will 
happily keep working and would make tons of commits on detached HEAD, 
and next time he switches to another branch, will lose all of them.
I guess that git does not let you commit on a detached head without 
crying out loud.
Wrong.  It cries out loud when you detach, not when you commit to a 
detached HEAD.  For good reason: Already at the second commit it would 
stop being funny.
Furthermore, one could do just a bit more than detaching, namely store 
the fact that head got detached and the name of the branch where the 
head was. With this, when the unconscious user types git status or git 
commit the system could alert him that head got detached because someone 
updated the branch behind his shoulders from remote...
And of course, you need a way to show the user all the updates the branch 
went through while the HEAD was detached, so that the user has a chance of 
understanding what happened in the meantime.

So much additional work, just to fix up the shortcomings of the 'detach' 
paradigm?  I take it as a clear mark of a not-so-elegant design.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:12

On Mon, Feb 16, 2009 at 12:43 PM, Johannes Schindelin
[off-list ref] wrote:
And of course, you need a way to show the user all the updates the branch
went through while the HEAD was detached, so that the user has a chance of
understanding what happened in the meantime.

So much additional work, just to fix up the shortcomings of the 'detach'
paradigm?  I take it as a clear mark of a not-so-elegant design.
You did plant a seed in my head with PUSH_HEAD though, and I'm still
thinking about it. :-)

I think the right thing is *not to detach*, but rather when pushing
into a non-bare repo for it to go into refs/remotes. Too bad clone
doesn't set it up this way by default when cloning from a non-bare
repo[*]. That would probably make more sense for new users.

[*] Clone can't currently know it's cloning from a non-bare repo, at
least via git://, as I recall...

j.

Re: disallowing push to currently checked-out branch

From: Sergio Callegari <hidden>
Date: 2016-06-15 22:46:12

Johannes Schindelin wrote:
Wrong.  It cries out loud when you detach, not when you commit to a 
detached HEAD.  For good reason: Already at the second commit it would 
stop being funny.
  
Right, I was wrong in expecting complaints. But... if it cried out at 
the first commit, for many people there would probably not be a second. 
Btw, I am ignorant on this: is there some case where one wants and has 
reasons to commit to a detached head before making a temporary branch on it?
  
quoted
Furthermore, one could do just a bit more than detaching, namely store 
the fact that head got detached and the name of the branch where the 
head was. With this, when the unconscious user types git status or git 
commit the system could alert him that head got detached because someone 
updated the branch behind his shoulders from remote...
    
And of course, you need a way to show the user all the updates the branch 
went through while the HEAD was detached, so that the user has a chance of 
understanding what happened in the meantime.
  
So much additional work, just to fix up the shortcomings of the 'detach' 
paradigm?  I take it as a clear mark of a not-so-elegant design.
  
Well not that much additional work...

when you push to the checked out branch, head gets detached and branch 
name (say /ref/heads/master) gets stored (say in .git/pre_push_branch).
when you run status or commit, you realize that there is a 
pre_push_branch and you give the warning, saying what the 
pre_push_branch was.
Now, since before the push you were at the tip of that branch, to know 
what happened it should be enough to ask the log (or the diff) from 
pre_push_branch to HEAD.
At the first user command that moves HEAD, pre_push_branch should get 
deleted.
Btw, what does happen now if you delete the branch the remote worktree 
is on? Don't you get a "dangling" head pointing to a non-existing branch 
and the system claiming that it is at the initial commit? Maybe, this 
too is a bit inelegant. In the other scenario, you would get a detached 
head and in pre_push_branch the info the name of a no more existing 
branch (mainig clear that you were on a branch that got deleted) and 
this info could be returned to the user.

Of course, I am not claiming that forbidding pushes to branches with 
checked out tree is bad. It is a good idea in my opinion.
I am just suggesting that one still wanting to allow that push in spite 
of all the potential consequences (namely wanting to mess with the 
relevant config variable), might prefer detaching head, storing the 
pre_push_branch and getting some info on status and commit rather than 
merely allowing the push.

In fact, I believe that the point is that with the current push-allowing 
behavior, when the push happens you loose the information about the 
precise commit against which the changes in the worktree were made. 
Which might be a useful piece of info.

Ciao,

Sergio

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:12

Hi,

On Mon, 16 Feb 2009, Jay Soffian wrote:
I think the right thing is *not to detach*, but rather when pushing
into a non-bare repo for it to go into refs/remotes.
I do not think that is consistent.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Mon, Feb 16, 2009 at 3:02 PM, Johannes Schindelin
[off-list ref] wrote:
Hi,

On Mon, 16 Feb 2009, Jay Soffian wrote:
quoted
I think the right thing is *not to detach*, but rather when pushing
into a non-bare repo for it to go into refs/remotes.
I do not think that is consistent.
Not consistent with what?

So let's say I have a workstation and a laptop. The "sane" thing to do
is probably something like this:

workstation$ mkdir project && cd project && git init
workstation$ (add, commit, ...)
workstation$ git clone --bare . ../project.git
workstation$ git remote add origin ../project.git
laptop$ git clone ssh://workstation/~/project.git project

And now I have two non-bare working repos with the intermediate bare
repo. So at both ends I can push/pull in the way that the designers of
git had in mind. :-)

But I don't think this recipe is well documented for beginners. So
they end up w/o the intermediate bare repository, and all the ensues.

IOW, I think pushing into refs/remotes makes sense in the situation
where the user has two non-bare repos that they want to exchange
commits between.

j.

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Mon, 16 Feb 2009, Sergio Callegari wrote:
Johannes Schindelin wrote:
quoted
Wrong.  It cries out loud when you detach, not when you commit to a 
detached HEAD.  For good reason: Already at the second commit it would 
stop being funny.
Right, I was wrong in expecting complaints. But... if it cried out at 
the first commit, for many people there would probably not be a second. 
What you are suggesting, though, is that the _pusher_ detaches the HEAD.  
So the _local_ user will never know.
Btw, I am ignorant on this: is there some case where one wants and has 
reasons to commit to a detached head before making a temporary branch on 
it?
Yes.  When you try fixups on a commit you just jumped to, for example.  Or 
when bisecting.

I often use the detached HEAD as kind of a stash during a bisect.  I try 
to fix it there, at the bad commit, and then cherry-pick HEAD@{1} into 
the branch after resetting the bisect.
quoted
quoted
Furthermore, one could do just a bit more than detaching, namely 
store the fact that head got detached and the name of the branch 
where the head was. With this, when the unconscious user types git 
status or git commit the system could alert him that head got 
detached because someone updated the branch behind his shoulders 
from remote...
And of course, you need a way to show the user all the updates the branch
went through while the HEAD was detached, so that the user has a chance of
understanding what happened in the meantime.

So much additional work, just to fix up the shortcomings of the 
'detach' paradigm?  I take it as a clear mark of a not-so-elegant 
design.
  
Well not that much additional work...

when you push to the checked out branch, head gets detached and branch name
(say /ref/heads/master) gets stored (say in .git/pre_push_branch).
when you run status or commit, you realize that there is a pre_push_branch and
you give the warning, saying what the pre_push_branch was.
Of course, you assume there that it was only one push between detaching 
the HEAD and inspecting the mess.
Now, since before the push you were at the tip of that branch, to know 
what happened it should be enough to ask the log (or the diff) from 
pre_push_branch to HEAD. At the first user command that moves HEAD, 
pre_push_branch should get deleted.
And you call that not much work?
Btw, what does happen now if you delete the branch the remote worktree 
is on?
See the related discussion of receive.denyDeleteCurrent.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Mon, Feb 16, 2009 at 3:09 PM, Johannes Schindelin
[off-list ref] wrote:
What you are suggesting, though, is that the _pusher_ detaches the HEAD.
So the _local_ user will never know.
I'm going to be presumptuous here and say that I think that you're
thinking about this the wrong way.

I would wager that when someone is pushing into a non-bare repo, it is
very likely that the pusher and the local user are the same person.
i.e., there are two common combinations: 1) a shared bare repo; 2) an
individual (non-shared) non-bare repo.

I think it is the shared non-bare repo which is rather uncommon, and
used mostly by advanced users or for specialized situations like
publishing web-roots.

If I'm right, then I still think that what might better sense is:


non-bare repo                     non-bare repo
-------------------               ---------------------
refs/heads            ---push-->  refs/remotes/incoming
   ^                                     |
   |                                   merge
 merge                                   |
   |                                     v
refs/remotes/origin   <--fetch--  refs/heads


Yes, you can set this up, but it is quite a few extra steps to do so.
The defaults assume there is a bare repo that you're pulling/pushing
from/to, hence the confusion for new users when that's not the
scenario they are in.

But instead of all this talk, maybe I should pony up some RFC patches. :-)

j.

Re: disallowing push to currently checked-out branch

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:13

Sergio Callegari [off-list ref] writes:
... 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.

If you want a push to the current branch of _your_ repository detach HEAD
automatically and record which branch it was pointing at before you
detached, I am reasonably sure you can do that in post-receive hook, no?

I do not think it is such a bad thing to have a new value 'detach' to
receive.denyCurrentBranch as a possible non-default choice per-se, but the
earlier discussion Jeff pointed out is only showing that detaching alone
is not enough to help the user recover from the resulting state, and Dscho
discussed in this thread that detaching and recording the original branch
may not be enough either.  IOW, we do not know yet precisely what needs to
happen other than detaching HEAD when the configuration tells us to
'detach' to be useful.

So how about you experiment the workflow by setting the configuration to
'ignore', setting up a hook to detach _and do some other useful things_ as
necessary, and help all of us figuring out what other information is
useful to record when you receive such a push, and what new indications
you could give users to reduce the possibility of confusion?  Once we know
what we want to happen, we can have it as one of the canned choices and it
would help users.

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Mon, 16 Feb 2009, Jay Soffian wrote:
On Mon, Feb 16, 2009 at 3:02 PM, Johannes Schindelin
[off-list ref] wrote:
quoted
On Mon, 16 Feb 2009, Jay Soffian wrote:
quoted
I think the right thing is *not to detach*, but rather when pushing 
into a non-bare repo for it to go into refs/remotes.
I do not think that is consistent.
Not consistent with what?
With pushing into bare repositories.  And worse, with the existing mode of 
operation.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Mon, Feb 16, 2009 at 4:15 PM, Johannes Schindelin
[off-list ref] wrote:
quoted
Not consistent with what?
With pushing into bare repositories.  And worse, with the existing mode of
operation.
I don't understand why pushing into a bare repo should have the same
behavior as pushing into a non-bare repo. They are different workflows
after-all.

j.

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

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 05:28:38PM -0500, Jay Soffian wrote:
On Mon, Feb 16, 2009 at 4:15 PM, Johannes Schindelin
[off-list ref] wrote:
quoted
quoted
Not consistent with what?
With pushing into bare repositories.  And worse, with the existing mode of
operation.
I don't understand why pushing into a bare repo should have the same
behavior as pushing into a non-bare repo. They are different workflows
after-all.
Actually, I think it is pulling from the non-bare repo that will get
confusing.

You are proposing to push, when pushing into a non-bare repo, into a
push refspec like refs/incoming/ (for example). But what is your fetch
refspec?

If it fetches as usual from refs/heads/, then you have an asymmetry.
That is, if I do "git push" on one client, then "git pull" on another
won't fetch the changes. I have to wait for the non-bare repo to pull
them into its refs/heads/ hierarchy (one by one, if there are multiple
branches).

So you can try putting refs/incoming into your fetch refspec if it is a
non-bare repo. But there are two issues there:

  - how do you know the remote is non-bare?

  - now you have to "push" in the non-bare upstream in order to make
    commits available. So it no longer works to do:

       workstation$ cd repo && hack hack hack && commit commit commit
       laptop$ git clone workstation:repo

    since you will silently end up with stale results.

    In some ways, this is nicely rigorous: non-bare repos become
    essentially "uncontactable" remotely, and you have a de facto bare
    repo in the form of refs/incoming sitting in between. But I'm not
    sure it matches what most users want to do, and certainly it causes
    more breakage to their workflows than receive.denyCurrentBranch.

-Peff

Re: disallowing push to currently checked-out branch

From: Sergio Callegari <hidden>
Date: 2016-06-15 22:46:13

Johannes Schindelin wrote:
What you are suggesting, though, is that the _pusher_ detaches the HEAD.  
So the _local_ user will never know.

  
I am not sure that I get what you mean.  But if I get it right, the only 
reason why the local
user cannot know is precisely because "git commit" does not complain if 
you call it from a detached head.
Otherwise the local user would find out that a push happened behind his 
shoulder right at the first "status" or "commit", as he was expecting to 
be on a branch and he finds himself off it.
quoted
Btw, I am ignorant on this: is there some case where one wants and has 
reasons to commit to a detached head before making a temporary branch on 
it?
    
Yes.  When you try fixups on a commit you just jumped to, for example.  Or 
when bisecting.

I often use the detached HEAD as kind of a stash during a bisect.  I try 
to fix it there, at the bad commit, and then cherry-pick HEAD@{1} into 
the branch after resetting the bisect.

  
Interesting.  But it is sort of abusing the detached head thing, isn't 
it? You use it as a temporary unnamed branch, and it becomes the tip of 
a short-lived development burst... It is not anymore just a way to peek 
at some status as I remember it was initially introduced, is it?
quoted
quoted
quoted
Furthermore, one could do just a bit more than detaching, namely 
store the fact that head got detached and the name of the branch 
where the head was. With this, when the unconscious user types git 
status or git commit the system could alert him that head got 
detached because someone updated the branch behind his shoulders 
from remote...
        
And of course, you need a way to show the user all the updates the branch
went through while the HEAD was detached, so that the user has a chance of
understanding what happened in the meantime.

So much additional work, just to fix up the shortcomings of the 
'detach' paradigm?  I take it as a clear mark of a not-so-elegant 
design.
      
  
Well not that much additional work...

when you push to the checked out branch, head gets detached and branch name
(say /ref/heads/master) gets stored (say in .git/pre_push_branch).
when you run status or commit, you realize that there is a pre_push_branch and
you give the warning, saying what the pre_push_branch was.
    
Of course, you assume there that it was only one push between detaching 
the HEAD and inspecting the mess.
  
After the first push, the head is already detached, so pre_push_branch 
does not get touched by the second, the third, the forth push, etc...
Which I guess is what the local user should want. He expected to be at 
some commit at the tip of some branch and he needs to find out what has 
happened between that commit and the new tip of that branch. Does he 
really need to know in how many and what precise push operations the 
branch tip moved?
quoted
Now, since before the push you were at the tip of that branch, to know 
what happened it should be enough to ask the log (or the diff) from 
pre_push_branch to HEAD. At the first user command that moves HEAD, 
pre_push_branch should get deleted.
    
And you call that not much work?

  
quoted
Btw, what does happen now if you delete the branch the remote worktree 
is on?
    
  
I tried.  With current git 1.6.1.3,  head remains pointing at a non 
existent branch and git status thinks that you need to do your initial 
commit.
When you commit, the deleted branch is immediately recreated from 
scratch and you loose the history that got you at that status.

Which brings me back to my former consideration.

I initially thought of detaching head because it looks like a way to 
save a bit of info that I would like to see preserved.  When someone 
pushes in my repo, if my current branch tip moves, at the first action 
that I attempt on the repo I would like to see a big alert that it did 
and have an easy way to find out at what commit I was before the push 
happened.  Otherwise, I cannot really find out what the push precisely 
changed, I cannot easily revert it if it was wrong, etc.

Sergio

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Tue, 17 Feb 2009, Sergio Callegari wrote:
Johannes Schindelin wrote:
quoted
What you are suggesting, though, is that the _pusher_ detaches the 
HEAD.  So the _local_ user will never know.
the only reason why the local user cannot know is precisely because "git 
commit" does not complain if you call it from a detached head.
No, the only reason is that you sneakily detached the HEAD behind his 
back.  It is not possible in physical life -- at least not without the 
owner of the head noticing -- and it should not be possible with Git, 
either.

All this "we need more complaining" is just a fix up for a failed design.
quoted
quoted
Btw, I am ignorant on this: is there some case where one wants and 
has reasons to commit to a detached head before making a temporary 
branch on it?
Yes.  When you try fixups on a commit you just jumped to, for example.  
Or when bisecting.

I often use the detached HEAD as kind of a stash during a bisect.  I 
try to fix it there, at the bad commit, and then cherry-pick HEAD@{1} 
into the branch after resetting the bisect.
Interesting.  But it is sort of abusing the detached head thing, isn't 
it? You use it as a temporary unnamed branch,
That is exactly what a detached HEAD is.
quoted
Of course, you assume there that it was only one push between 
detaching the HEAD and inspecting the mess.
After the first push, the head is already detached, so pre_push_branch 
does not get touched by the second, the third, the forth push, etc...
Oh, so the user should be really fscked for not realizing just how much 
happened in the meantime?
quoted
quoted
Now, since before the push you were at the tip of that branch, to 
know what happened it should be enough to ask the log (or the diff) 
from pre_push_branch to HEAD. At the first user command that moves 
HEAD, pre_push_branch should get deleted.
quoted
And you call that not much work?
That point is still valid.  If you have to do too much to make your idea 
work, if you have to bolt on this and that, it is a sure sign that the 
design is borked.
quoted
quoted
Btw, what does happen now if you delete the branch the remote 
worktree is on?
I tried.  With current git 1.6.1.3, head remains pointing at a non 
existent branch and git status thinks that you need to do your initial 
commit. When you commit, the deleted branch is immediately recreated 
from scratch and you loose the history that got you at that status.
As I remarked already, this is a bug that is actively being squashed.

Of course, you can go on and on and on with the detached HEAD ide, but so 
far you haven't convinced me that this is a sensible thing to do.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Sergio Callegari <hidden>
Date: 2016-06-15 22:46:13

Johannes Schindelin wrote:
Of course, you can go on and on and on with the detached HEAD ide, but so 
far you haven't convinced me that this is a sensible thing to do.
  
I will not... it's time to sleep where I am! And I am just a user of git 
and you are a developer, which makes me think that you might know much 
better.
But the exchange was insightful, thanks.

Rather, I'll turn again the question...

Let us assume that I am working on branch B and that my worktree is 
based on commit XYZ. Let's also assume that someone pushes behind my 
shoulders and moves the tip of B (or even deletes B alltogether) either 
in one or in multiple pushes.  Is there an easy way so that I can now 
find out at what commit (XYZ) I was before the push(es)?  That would 
already make me quite satisfied, because with this I can write wrappers 
or aliases that can check the HEAD against that commit on every 
status/commit operation and warn the user just in case.

Sergio
Ciao,
Dscho

  

Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Tue, 17 Feb 2009, Sergio Callegari wrote:
Let us assume that I am working on branch B and that my worktree is based on
commit XYZ. Let's also assume that someone pushes behind my shoulders and
moves the tip of B (or even deletes B alltogether) either in one or in
multiple pushes.  Is there an easy way so that I can now find out at what
commit (XYZ) I was before the push(es)?
Nope.  There was code flying around at some stage to record in the index 
what commit it was based on.

I forgot why it was thrown out again; you'll have to look up the 
discussion yourself.

Ciao,
Dscho

Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Mon, Feb 16, 2009 at 5:52 PM, Jeff King [off-list ref] wrote:
Actually, I think it is pulling from the non-bare repo that will get
confusing.

You are proposing to push, when pushing into a non-bare repo, into a
push refspec like refs/incoming/ (for example). But what is your fetch
refspec?

If it fetches as usual from refs/heads/, then you have an asymmetry.
That is, if I do "git push" on one client, then "git pull" on another
won't fetch the changes. I have to wait for the non-bare repo to pull
them into its refs/heads/ hierarchy (one by one, if there are multiple
branches).

So you can try putting refs/incoming into your fetch refspec if it is a
non-bare repo. But there are two issues there:

 - how do you know the remote is non-bare?

 - now you have to "push" in the non-bare upstream in order to make
   commits available. So it no longer works to do:

      workstation$ cd repo && hack hack hack && commit commit commit
      laptop$ git clone workstation:repo

   since you will silently end up with stale results.

   In some ways, this is nicely rigorous: non-bare repos become
   essentially "uncontactable" remotely, and you have a de facto bare
   repo in the form of refs/incoming sitting in between. But I'm not
   sure it matches what most users want to do, and certainly it causes
   more breakage to their workflows than receive.denyCurrentBranch.
My head is playing around with two ideas now that Dscho has mentioned:

receive.localBranches = (refuse | allow)

http://thread.gmane.org/gmane.comp.version-control.git/77955/focus=78065

And PUSH_HEAD.

The idea would be for side-pushes never to update a local branch, but
to be recorded in PUSH_HEAD. You'd be able to rebase/merge local
branch on-top of changes in PUSH_HEAD. I'm trying to figure out what
can make sense when pulling from such a repo.

j.

PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Tue, 17 Feb 2009, Jay Soffian wrote:
My head is playing around with two ideas now that Dscho has mentioned:

receive.localBranches = (refuse | allow)

http://thread.gmane.org/gmane.comp.version-control.git/77955/focus=78065
In the meantime, we have receive.denyCurrentBranch, which is much superior 
to the localBranches design: it tackles the _real_ issue -- the only 
reason why a current branch cannot be updated lightly is that it might 
have a working directory which would be forced out-of-sync.
And PUSH_HEAD.

The idea would be for side-pushes never to update a local branch, but to 
be recorded in PUSH_HEAD. You'd be able to rebase/merge local branch 
on-top of changes in PUSH_HEAD. I'm trying to figure out what can make 
sense when pulling from such a repo.
Sorry, I should clarify what I mean by PUSH_HEAD:

The idea is to have the _same_ as FETCH_HEAD, i.e. a simple file 
(.git/FETCH_HEAD) listing all the branch tips that have been pushed, _no 
matter_ if they were successfully stored as refs.

Just do this in a repository which is lagging behind origin a little:

	$ git fetch origin

and then see that a file .git/FETCH_HEAD exists.  As long as you are only 
interested in the first rev, you can even use "FETCH_HEAD" as a rev name:

	$ git show FETCH_HEAD

The important feature of this method is that FETCH_HEAD is not fetchable.  
Neither 'ls-remote' nor 'branch' will show it.

BTW a PUSH_HEAD could also help the issue that when updating of a ref was 
refused, all the objects will have to be transferred via the wire again 
when pushing somewhere else.

Having said all that, I can easily live without PUSH_HEAD.

Ciao,
Dscho

Re: PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Tue, Feb 17, 2009 at 6:28 AM, Johannes Schindelin
[off-list ref] wrote:
quoted
receive.localBranches = (refuse | allow)

http://thread.gmane.org/gmane.comp.version-control.git/77955/focus=78065
In the meantime, we have receive.denyCurrentBranch, which is much superior
to the localBranches design: it tackles the _real_ issue -- the only
reason why a current branch cannot be updated lightly is that it might
have a working directory which would be forced out-of-sync.
Hmpfh.

So both you and Junio have changed your mind since that thread then.
Because in that thread, you propose  receive.guardCurrentBranch, which
was quite similar to today's receive.denyCurrentBranch. Junio then
argues that treating just the checked-out branch as special, as
opposed to all local branches is not the right thing to do:
--- snip ---
http://thread.gmane.org/gmane.comp.version-control.git/77955/focus=78062

Step back a bit and think _why_ you wanted to prevent current branch tip
from getting updated in the first place.  There are two issues:

 * Why is it _current_ branch, and not _these branches_, that can be
   configured by the user to be protected from a push from sideways?

 * Why is it undesirable for the work tree and the index to go out of sync
   with respect to the branch tip to begin with?

The latter is simpler to answer, so let's deal with it first.  The reason
why it is bad is because allowing a push to the current branch interferes
with the work actively being done in the repository, using the work tree
contents.  There is a person, you, who is actively editing the work tree
in order to advance the tip of the branch by making commits.  If the
branch tip moves without your knowing, that destabilizes your working
environment.  Your work tree wanted to make a new commit on top of some
known state, but that state was moved underneath you.  Not good.

When you are using the repository for real work (i.e. advance the tips of
its branches), you want a stable environment.  You do not want its HEAD
bobbing around outside your control, and silently detaching to cause your
later commits to go to unnamed branch without your knowing is just as bad
(which you already correctly objected to).
--- snip ---
And you end up agreeing:
--- snip ---
http://thread.gmane.org/gmane.comp.version-control.git/77955/focus=78062
Now think.  What if one of these operations you do in the repository to
advance the tip was to merge from one of _your_ local branches?  Yes,
you end up merging something you did not expect to merge if you allowed
a push from sideways to affect that local branch, only because the
branch happened to be un-checked-out and you implemented this protection
to forbid only to current branch.  Allowing a push from sideways to any
local branch destabilizes your work environment, not just the current
one.
Okay, I am starting to see the light.

How about

	receive.localBranches = (refuse | allow)
--- snip ---
Then the thread died, with receive.localBranches going into TODO, but
never got an implementation. Sometime later, receive.denyCurrentBranch
came along, which is the original idea you proposed, Junio argued
against, and then you agreed.

So, I'm not sure what happened in the intervening time between the
receive.localBranches proposal and the receive.denyCurrentBranch
implementation that suddenly what is basically guardCurrentBranch
became a good idea.

But, I happen to agree with Junio's argument in gmane 77955.

j.

Re: PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Jeff King <hidden>
Date: 2016-06-15 22:46:13

On Tue, Feb 17, 2009 at 12:29:53PM -0500, Jay Soffian wrote:
So both you and Junio have changed your mind since that thread then.
Because in that thread, you propose  receive.guardCurrentBranch, which
was quite similar to today's receive.denyCurrentBranch. Junio then
argues that treating just the checked-out branch as special, as
opposed to all local branches is not the right thing to do:
I have to admit, I found that thread a very interesting read, because I
somehow missed it the first time and it seemed the opposite of what
happened later.
So, I'm not sure what happened in the intervening time between the
receive.localBranches proposal and the receive.denyCurrentBranch
implementation that suddenly what is basically guardCurrentBranch
became a good idea.
I think what happened (partially) is that I never read the original,
then at GitTogether somebody (Sam?) was complaining about usability
issues, so I wrote the denyCurrentBranch patch. Why and how people
changed their minds is a mystery to me, though.

-Peff

PS I seem to have an uncanny knack for writing a patch, then finding out
that Dscho wrote the exact same patch months or years earlier. I think
this is the third time it has happened.

Re: PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:13

Jay Soffian [off-list ref] writes:
So both you and Junio have changed your mind since that thread then.
At least I didn't.

I personally was not too worried about protecting either local branches
nor the current branch (and I do not lose sleep over them now either).
Either is about forbidding an end user who knows from doing an operation
we have allowed so far, only because an abuse of the feature by other end
users who either don't know what they are doing or are careless can result
in confusing the latter.  I do not particularly like that kind of safety
valve.

The current round of protecting only local branches is there because it is
of much lessor impact, with simpler code (and easier revertibility if
needed), than the full blown "protect these branches" one in which issues
in its design still has to be ironed out if we go that route (see my other
message from yesterday to Jeff --- we discuss exactly that in the context
of detached HEAD and other operations).  The need for "current branch
protection" this round implements also comes from an observed confusions
in real world users Dscho and others saw on #git and other places.  The
more general "protect these branches" is conceptually nicer but the need
for such safeguard is still under discussion as far as I understood what
was said in the recent discussions.

Re: PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:13

On Tue, Feb 17, 2009 at 5:20 PM, Junio C Hamano [off-list ref] wrote:
Jay Soffian [off-list ref] writes:
quoted
So both you and Junio have changed your mind since that thread then.
At least I didn't.
Ah, I didn't mean to mischaracterize your intent from that thread then.
I personally was not too worried about protecting either local branches
nor the current branch (and I do not lose sleep over them now either).
Either is about forbidding an end user who knows from doing an operation
we have allowed so far, only because an abuse of the feature by other end
users who either don't know what they are doing or are careless can result
in confusing the latter.  I do not particularly like that kind of safety
valve.

The current round of protecting only local branches is there because it is
of much lessor impact, with simpler code (and easier revertibility if
needed), than the full blown "protect these branches" one in which issues
in its design still has to be ironed out if we go that route (see my other
message from yesterday to Jeff --- we discuss exactly that in the context
of detached HEAD and other operations).  The need for "current branch
protection" this round implements also comes from an observed confusions
in real world users Dscho and others saw on #git and other places.  The
more general "protect these branches" is conceptually nicer but the need
for such safeguard is still under discussion as far as I understood what
was said in the recent discussions.
Okay, that makes sense.

j.

Re: PUSH_HEAD, was Re: disallowing push to currently checked-out branch

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:13

Hi,

On Tue, 17 Feb 2009, Jay Soffian wrote:
So both you and Junio have changed your mind since that thread then.
I never claimed to be unable to learn.

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