Re: receive.denyCurrentBranch
- From
Jay Soffian <jaysoffian@gmail.com>
- Date
- Feb 9, 2009, 01:47 UTC
- Message-ID
- <76718490902081747s7a1ebe12yaf08665429a594c6@mail.gmail.com>
- In-Reply-To
- <alpine.DEB.1.00.0902090038550.10279@pacific.mpi-cbg.de>
On Sun, Feb 8, 2009 at 6:41 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 10 quoted lines
> Hi, > > On Sun, 8 Feb 2009, Jay Soffian wrote: > >> If you had paid attention, you would have noticed that Mercurial did not >> attempt to merge. Rather, it created a new branch head in the remote >> repository. > > So this is the "detached HEAD" idea. Which contradicts the law of the > least surprise.
I agree that a detached HEAD is a bad idea. The closest parallel that I can come up with for git would be for receive-pack to store incoming changes into separate branch hierarchy, NOT for it to detach HEAD. A toy-patch I played around with earlier allowed this on the non-bare upstream repo:
[receive]
prefix = refs/remotes/incomingThen a push to refs/heads/master was automatically stored as refs/remotes/incoming/master instead.
And yes, I'm aware the user can use a push refspec on the sending side.
> It should be clear that the equivalent of a central repository is a bare > repository. And hopefully Junio's strategy will make that clearer, so I > think this is the superior approach.
I foresee new user doing this:
laptop:~$ git clone ssh://workstation/~/repo laptop:~$ cd repo laptop:~/repo (master)$ echo change >> file && git commit -am change laptop:~/repo (master)$ git push ... error: refusing to update checked out branch: refs/heads/master To ssh://workstation/~/repo ! [remote rejected] master -> master (branch is currently checked out) error: failed to push some refs to 'ssh://workstation/~/repo'
And now new user is stumped.
Perhaps adding something like this to the git-push man page:
---8<---
Non-bare Repositories --------------------- When pushing to a non-bare upstream repository (i.e. an upstream repository with a working copy), changes to the checked out branch are NOT reflected in the upstream index, nor in the working copy. This creates a situation where it is easy to accidentally revert the changes on the next commit in the upstream repository.
e.g. Assume the following history exists in the upstream repository:
A---B master
master is the currently checked out branch, nothing is staged in the index and the working copy is clean.
A single change is made to master downstream and pushed. The upstream repository is now in this state:
A---B---C master
However, the index and working copy reflect the state at commit B. Performing a new commit in the upstream repository would do this:
A---B---C---B' master
B' is a new commit, but reflects the same state as B.
In order to prevent this situation, it is recommended that if you need to push into a non-bare upstream repository, set receive.denyCurrentBranch = true in the upstream repository (this will become the default in git-X.Y). This will prevent the push from occurring. Instead, you can push into an alternate branch, and then merge that branch in the upstream repository. e.g.:
server$ cd ~/repo && git config receive.denyCurrentBranch true
laptop$ git push ... error: refusing to update checked out branch: refs/heads/master To ssh://server/~/repo ! [remote rejected] master -> master (branch is currently checked out) error: failed to push some refs to 'ssh://server/~/repo' laptop$ git push origin master:refs/remotes/laptop/master laptop$ ssh server server$ cd ~/repo server$ git merge laptop/master
Alternatively, you can set receive.denyCurrentBranch = warn in the upstream repo, but then you must remember to perform "git reset --hard" in the upstream repo after pushing to its currently checked out branch. (But be careful, as "git reset --hard" throws away uncommitted changes.)
---8<---
j.