Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the consequences of using receive.denyCurrentBranch in Git?

People also ask

What happens when we push the code in git?

The git push command is used to upload local repository content to a remote repository. Pushing is how you transfer commits from your local repository to a remote repo. It's the counterpart to git fetch , but whereas fetching imports commits to local branches, pushing exports commits to remote branches.

What are the benefits of adding a remote in git?

The git remote command lets you create, view, and delete connections to other repositories. Remote connections are more like bookmarks rather than direct links into other repositories.

What happens if I git push in a branch?

After you make and commit changes locally, you can share them with the remote repository using git push . Pushing changes to the remote makes your commits accessible to others who you may be collaborating with. This will also update any open pull requests with the branch that you're working on.

What is git bare repository?

What is a bare repository? A bare repository is the same as default, but no commits can be made in a bare repository. The changes made in projects cannot be tracked by a bare repository as it doesn't have a working tree. A working tree is a directory in which all the project files/sub-directories reside.


The server where you are pushing to should use bare repository.

How to convert a normal Git repository to a bare one?


Why Git won't let you push to non-bare repositories

The original poster says:

One solution is to run the following command:

git config receive.denyCurrentBranch ignore

After this it works, but I would like to know why I need to use this option. Is this the only option? What are the consequences of doing this?

As I point out in my answer to a similar question, since Git version 1.6.2, Git won't let you push to a non-bare repository by default. This is because the git push command only updates the branch and HEAD references on the remote repository. What it doesn't do is also update the working-copy and staging-area in that non-bare remote.

As a consequence, when you use git status in the remote repo, you'll see that the repo's previous state is still present in the working copy (and staged in the index):

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   previous-state.txt

If you look at the error message that you got when you first tried to push to your non-bare remote repo with the receive.denyCurrentBranch setting set to the default refuse value, you'll see that the message tells you basically the same thing:

error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error:
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.

You should really just push to bare Git repositories

As pointed out in some of the other answers, you shouldn't really be pushing to a non-bare repository, for the reasons I pointed out above, and which Git itself is telling you.

So like what this answer states, a simple way to convert an existing non-bare repo to a bare one is to simply reclone it as a bare repo:

git clone --bare old-repo

Or you could try messing around with the core.bare config setting, as detailed in this answer.


I had the same error and needed the repository to be running as a dev test page online (that is, I guess, to keep a non-bare repo). Hopefully I solved it by initiating the repository with this series of commands (since git 2.3):

git init
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
git commit
git config receive.denyCurrentBranch updateInstead

As seen here: cannot push into git repository


You should have a bare repository on the server, not one with a checked-out working tree. Git is telling you it refuses to overwrite the branch that is currently checked out on the server.

See this answer for information on how to convert your non-bare repository on the server to a bare one.


Autopsy of the Problem

When a branch is checked out, committing will add a new commit with the current branch's head as its parent and move the branch's head to be that new commit.

So

A ← B
    ↑
[HEAD,branch1]

becomes

A ← B ← C
        ↑
    [HEAD,branch1]

But if someone could push to that branch inbetween, the user would get itself in what git calls detached head mode:

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Now the user is not in branch1 anymore, without having explicitly asked to check out another branch. Worse, the user is now outside any branch, and any new commit will just be dangling:

     [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Hypothetically, if at this point, the user checks out another branch, then this dangling commit becomes fair game for Git's garbage collector.