Git Push error: refusing to update checked out branch

I solved this problem by first verifying the that remote did not have anything checked out (it really was not supposed to), and then made it bare with:

$ git config --bool core.bare true

After that git push worked fine.


For me, the following did the trick:

git config --global receive.denyCurrentBranch updateInstead

I set up drive F:, almost in its entirety, to sync between my Windows 10 desktop and my Windows 10 laptop, using Git. I ended up running the above command on both machines.

First I shared the desktop's F drive on the network. Then I was able to clone it on my laptop by running:

F:
git clone 'file://///DESKTOP-PC/f'

Unfortunately, all the files ended up under "F:\f" on my laptop, not under F:\ directly. But I was able to cut and paste them manually. Git still worked from the new location afterwards.

Then I tried making some changes to files on the laptop, committing them, and pushing them back to the desktop. That didn't work until I ran the git config command mentioned above.

Note that I ran all these commands from within Windows PowerShell, on both machines.

UPDATE: I still had issues pushing changes, in some cases. I finally just started pulling changes instead, by running the following on the computer I want to pull the latest commit(s) to:

git pull --all --prune

Summary

You cannot push to the one checked out branch of a repository because it would mess with the user of that repository in a way that will most probably end with loss of data and history. But you can push to any other branch of the same repository.

As bare repositories never have any branch checked out, you can always push to any branch of a bare repository.

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.


Reason:You are pushing to a Non-Bare Repository

There are two types of repositories: bare and non-bare

Bare repositories do not have a working copy and you can push to them. Those are the types of repositories you get in Github! If you want to create a bare repository, you can use

git init --bare

So, in short, you can't push to a non-bare repository (Edit: Well, you can't push to the currently checked out branch of a repository. With a bare repository, you can push to any branch since none are checked out. Although possible, pushing to non-bare repositories is not common). What you can do, is to fetch and merge from the other repository. This is how the pull request that you can see in Github works. You ask them to pull from you, and you don't force-push into them.


Update: Thanks to VonC for pointing this out, in the latest git versions (currently 2.3.0), pushing to the checked out branch of a non-bare repository is possible. Nevertheless, you still cannot push to a dirty working tree, which is not a safe operation anyway.

Tags:

Git

Git Push