Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git Push error: refusing to update checked out branch

Tags:

git

git-push

People also ask

How do I push a checked out branch?

Create a new branch with the branch, switch or checkout commands. Perform a git push with the –set-upstream option to set the remote repo for the new branch. Continue to perform Git commits locally on the new branch. Simply use a git push origin command on subsequent pushes of the new branch to the remote repo.

Why git push does not work?

If git push origin master not working , all you need to do is edit that file with your favourite editor and change the URL = setting to your new location. Assuming the new repository is correctly set up and you have your URL right, you'll easily be able to push and pull to and from your new remote location.

How do I force git push?

To force a push to only one branch, use a + in front of the refspec to push (e.g git push origin +master to force a push to the master branch).

Which error would you get if you try to push master branch changes to a remote repository?

The error message error: refusing to update checked out branch: refs/heads/master is emitted by the remote repository and it means you're trying to push code to remote non-bare repository that has different code currently checked out in the working directory.


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.


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.


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.


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

cd into the repo/directory that you're pushing into on the remote machine and enter

$ git config core.bare true

As there's already an existing repository, running

git config --bool core.bare true

on the remote repository should suffice

From the core.bare documentation

If true (bare = true), the repository is assumed to be bare with no working directory associated. If this is the case a number of commands that require a working directory will be disabled, such as git-add or git-merge (but you will be able to push to it).

This setting is automatically guessed by git-clone or git-init when the repository is created. By default a repository that ends in "/.git" is assumed to be not bare (bare = false), while all other repositories are assumed to be bare (bare = true).