What is this Git warning message when pushing changes to a remote repository?
Asked Answered
T

3

87

The description is a bit terse. I simply added a file on my local master branch and pushed it back to a remote repo. Any idea why this is coming up?

warning: updating the current branch
warning: Updating the currently checked out branch may cause confusion,
warning: as the index and work tree do not reflect changes that are in HEAD.
warning: As a result, you may see the changes you just pushed into it
warning: reverted when you run 'git diff' over there, and you may want
warning: to run 'git reset --hard' before starting to work to recover.
warning: 
warning: You can set 'receive.denyCurrentBranch' configuration variable to
warning: 'refuse' in the remote repository to forbid pushing into its
warning: current branch.
warning: To allow pushing into the current branch, you can set it to 'ignore';
warning: but this is not recommended unless you arranged to update its work
warning: tree to match what you pushed in some other way.
warning: 
warning: To squelch this message, you can set it to 'warn'.
warning: 
warning: Note that the default will change in a future version of git
warning: to refuse updating the current branch unless you have the
warning: configuration variable set to either 'ignore' or 'warn'.   
Tl answered 29/4, 2009 at 22:23 Comment(3)
What were the exact commands that you used?Smalltime
Pushing to a non-bare repo is now more secure with Git 2.3.0 (February 2015), even if you are pushing to a checked out branch: see my answer below.Aikens
possible duplicate of What does git "updating currently checked out branch" warning mean?Palladin
R
59

Actually, it means pretty much exactly what it says: somebody is working in the repository that you are pushing to, and that somebody has currently checked out the exact same branch that you are pushing to.

This is very confusing, because now they think that they have checked out the latest version of the branch, when, in fact, you have just updated the branch to a newer version. So, when they now run git commit, their commit will essentially revert all the commits that you just pushed. And when they run git diff they will see the opposite of everything you just pushed, even though they maybe havn't even changed anything.

For that reason, it is generally considered bad practice to push to a non-bare repository; you should only ever push to bare repositories, i.e. repositories that do not have an attached working copy. At the very least you should make sure that you do not push to the currently checked-out branch, but generally you shouldn't just shove your code into someone else's repository, you should ask them to pull from you instead.

In some special cases, like when you are serving a website from a Git repository and you want to update the website by pushing to it, it actually makes sense to push to the currently checked-out branch, but in that case you must make sure that you have a hook installed that actually updates the checked-out working copy, otherwise your website will never be updated.

Roadwork answered 30/4, 2009 at 1:21 Comment(3)
The way I manage the website problem you mention in your last paragraph is to have a central bare repository that I push to, then I pull from that into the web site working directory. This method requires shell access to the web server, of course, where your hook method does not necessarily require that.Nullity
Jorg, thanks for the response. The shared repository shouldn't have a working directory, but I did not init it with --bare. It's use is for sharing work only. There is a "work" area, but no one uses it. Should I re-init with bare?Tl
Hmm -- I often work without a centralized repository. I'll work on code on my laptop and on a cluster computer with my analysis code. They are both my own repositories, and are somewhat like the special case you describe.Moist
A
167

With Git 2.3.0 (After February 2015)

If nobody is working in that remote non-bare repo, then it should be possible to push to a checked out branch.

But to be more secure in that operation, you now can (with Git 2.3.0, February 2015), do in that remote repo:

git config receive.denyCurrentBranch updateInstead

It is more secure than config receive.denyCurrentBranch=ignore: it will allow the push only if you are not overriding modification in progress.

See commit 1404bcb by Johannes Schindelin (dscho):

receive-pack: add another option for receive.denyCurrentBranch

When synchronizing between working directories, it can be handy to update the current branch via 'push' rather than 'pull', e.g. when pushing a fix from inside a VM, or when pushing a fix made on a user's machine (where the developer is not at liberty to install an ssh daemon let alone know the user's password).

The common workaround – pushing into a temporary branch and then merging on the other machine – is no longer necessary with this patch.

The new option is:

updateInstead

Update the working tree accordingly, but refuse to do so if there are any uncommitted changes.


The commit 4d7a5ce adds more tests, and mentions:

The previous one tests only the case where a path to be updated by the push-to-deploy has an incompatible change in the target's working tree that has already been added to the index, but the feature itself wants to require the working tree to be a lot cleaner than what is tested.

Add a handful more tests to protect the feature from future changes that mistakenly (from the viewpoint of the inventor of the feature) loosens the cleanliness requirement, namely:

  • A change only to the working tree but not to the index is still a change to be protected;
  • An untracked file in the working tree that would be overwritten by a push-to-deploy needs to be protected;
  • A change that happens to make a file identical to what is being pushed is still a change to be protected (i.e. the feature's cleanliness requirement is more strict than that of checkout).

Also, test that a stat-only change to the working tree is not a reason to reject a push-to-deploy.

With Git < 2.3.0 (Before February 2015)

The most common approach is to create a bare repository from the non-bare repository and have both the remote/local non-bare git repos point at the newly created bare repository.

Aikens answered 1/2, 2015 at 11:20 Comment(10)
This is extremely useful when pairing or frequently switching between different machines while trying to keep everything up to date. I also use this to keep my dev server up to date (it auto-restarts on code changes) while still being able to develop on it when I need to. This is really the solution the accepted answer is lacking imo.Mullen
@Thor84no indeed. And don't forget the push-to-checkout hook from git 2.4: https://mcmap.net/q/12164/-can-git-push-to-the-current-branch-of-a-remote-repository. Note: the accepted answer was correct at the time (it is six years old)Aikens
I'm using windows and git version 2.6.3.windows.1 and the I needed to remove the '=' i.e git config receive.denyCurrentBranch updateInsteadSubchloride
This didn't work for me, for git version 2.17.2 (on local and remote). I got "fatal: bad config value for 'receive.denycurrentbranch' in config". I needed to make it git config receive.denyCurrentBranch ignore . And after I git push origin master on the local side, I need to to a git checkout -f on the remote side.Headley
@MikeS Strange: updateInstead is part of the values mentioned in git-scm.com/docs/git-config#Documentation/…. Did you have that exact value (with the exact case) on the remote side?Aikens
updateInstead worked perfectly for me, thank you.Windlass
really apreciate your knowledgeRinehart
If you're using glitch, VonC's answer here is consistent with the glitch message board answer hereTelemechanics
This is super useful. Sometimes you just can't use bare repositories, for example, if you use a git GUI program that doesn't support bare repositories well or at all.Hako
This works for me: git push --receive-pack=/path/to/git-receive-pack. I have an up-to-date version of git locally but I was trying to push to my VPS with an old version of git-receive-pack in /usr/bin/. They have an up-to-date version of git-receive-pack in another location, I just had to explicitly tell git push where to find it.Elman
R
59

Actually, it means pretty much exactly what it says: somebody is working in the repository that you are pushing to, and that somebody has currently checked out the exact same branch that you are pushing to.

This is very confusing, because now they think that they have checked out the latest version of the branch, when, in fact, you have just updated the branch to a newer version. So, when they now run git commit, their commit will essentially revert all the commits that you just pushed. And when they run git diff they will see the opposite of everything you just pushed, even though they maybe havn't even changed anything.

For that reason, it is generally considered bad practice to push to a non-bare repository; you should only ever push to bare repositories, i.e. repositories that do not have an attached working copy. At the very least you should make sure that you do not push to the currently checked-out branch, but generally you shouldn't just shove your code into someone else's repository, you should ask them to pull from you instead.

In some special cases, like when you are serving a website from a Git repository and you want to update the website by pushing to it, it actually makes sense to push to the currently checked-out branch, but in that case you must make sure that you have a hook installed that actually updates the checked-out working copy, otherwise your website will never be updated.

Roadwork answered 30/4, 2009 at 1:21 Comment(3)
The way I manage the website problem you mention in your last paragraph is to have a central bare repository that I push to, then I pull from that into the web site working directory. This method requires shell access to the web server, of course, where your hook method does not necessarily require that.Nullity
Jorg, thanks for the response. The shared repository shouldn't have a working directory, but I did not init it with --bare. It's use is for sharing work only. There is a "work" area, but no one uses it. Should I re-init with bare?Tl
Hmm -- I often work without a centralized repository. I'll work on code on my laptop and on a cluster computer with my analysis code. They are both my own repositories, and are somewhat like the special case you describe.Moist
M
15

This is the same problem as This question, the solution is to use git init --bare or git clone --bare.

Myall answered 24/8, 2009 at 4:41 Comment(2)
It says that even on bare repo. (all I did is upgrade git software from version 1.5 to 1.7)Castra
It seems that upgrading from 1.5 to 1.7 will trigger this message. I did the "mv reponame reponame.old; git clone --bare reponame.old reponame" to resolve this. I also had to use "--shared=group" and fix the group permissions because I'm running a shared repo.Rheumatic

© 2022 - 2024 — McMap. All rights reserved.