MaDa MaDa - 3 years ago 128
Git Question

Why "git fetch origin branch:branch" works only on a non-current branch?

While working on a feature branch, I use this Git command to update my "develop" branch to the latest state, immediately before merging my feature branch with the "develop":

git fetch origin develop:develop


This works, i.e. the local "develop" points at the same commit as "origin/develop" and is in the latest state with origin.

Somehow, though, this command fails when the "develop" branch is checked out:

fatal: Refusing to fetch into current branch refs/heads/develop of non-bare repository
fatal: The remote end hung up unexpectedly


It would help me understand Git better, if I knew why it happens so.

Answer Source

The error message comes from builtin/fetch.c#check_not_current_branch().
That function goes all the way back to commit 8ee5d73, Oct. 2008, git 1.6.0.4

The comment is instructive:

Some confusing tutorials suggested that it would be a good idea to fetch into the current branch with something like this:

git fetch origin master:master

(or even worse: the same command line with "pull" instead of "fetch").
While it might make sense to store what you want to pull, it typically is plain wrong when the current branch is "master".
This should only be allowed when (an incorrect) "git pull origin master:master" tries to work around by giving --update-head-ok to underlying "git fetch", and otherwise we should refuse it, but somewhere along the lines we lost that behavior.

The check for the current branch is now only performed in non-bare repositories, which is an improvement from the original behaviour.

Considering that the function check_not_current_branch() is called with:

if (!update_head_ok)
        check_not_current_branch(ref_map);

That means a git fetch -u origin develop:develop should work.

-u
--update-head-ok

By default git fetch refuses to update the head which corresponds to the current branch. This flag disables the check.
This is purely for the internal use for git pull to communicate with git fetch, and unless you are implementing your own Porcelain you are not supposed to use it.

Even though you are not supposed to use that option, it does answer your initial requirement, making “git fetch origin branch:branch” work on a current branch.


Regarding the origin of this patch, follow the discussion there.

While it might make sense to store what you want to pull

That is the fetch part: it stores the remote history from the updated origin/master.
But that is especially broken when the current local branch is also master.
As mentioned in this answer:

I think "git fetch url side:master" when master is the current branch and we have omitted --update-head-ok is broken.
The test fails on current master.

It would also fail to update the working directory and would leave the index as if you're removing everything.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download