In my workplace, we just moved to Git for revision control after more than 10 years of using Source Safe (yay!). I now have to support our engineers in their learning of the new tool. It is important to note that we are all using the GitExtensions UI under Windows.
A couple of colleagues did the following (from the UI):
Here is what the UI of GitExtensions looks like when we do a pull (I sadly cannot post screen grabs from work):
Pull from: origin
Local branch: A
Remote branch: develop
Merge option: Merge remote branch into current branch
(Pull button is then pressed)
Here is what the command log of GitExtensions reveals it did for the pull:
git pull --progress "origin" +refs/heads/develop:refs/remotes/origin/A
After that command, the users saw a new origin/A remote tracking branch appear in their history, while we confirmed no branch A is present on origin.
I looked at the git pull manual to try and understand what happened, but I still cannot understand if what we are seeing is a GitExtensions bug or an misunderstanding on our part of what git pull should do.
Anyone can help me figure out what is happening here?
Thanks in advance
I know that pulling the remote develop branch into the local A branch does not make sense and I know how to resolve the situation by deleting the remote tracking branch. What I really want is to understand the logic behind the origin/A remote tracking branch being created in the first place, since no A branch was ever present on origin.
Thanks
It's hard to say whether this is a GitExtensions bug or not. In corporate environments, it's very unusual (almost always a mistake) to pull in anything other than the identically named remote branch, so I'm not surprised you got odd results. (I'd say it's a mistake to ever use git pull
due to its horrific design, but that's another story.)
The +refs/heads/develop:refs/remotes/origin/A
part is called a refspec (reference specification). It says to make the local destination reference named refs/remotes/origin/A
(abbreviated as origin/A
) point to the same commit that the remote repository's refs/heads/develop
reference (the develop
branch in the remote repository) is currently pointing to. The plus (+
) at the beginning says to force the ref to match even if the destination ref can't be fast-forwarded to the source ref.
Thus, the pull
command you mention causes Git to:
develop
branch is pointing torefs/remotes/origin/A
reference to point to that commitBased on the UI mock-up you provided, this is not what I would have expected to happen. I would have expected GitExtensions to run the following instead:
git pull --progress origin refs/heads/develop
By omitting the local ref name (the part after the colon), Git does the following:
develop
branch is pointing toFETCH_HEAD
temporary reference to point to that commitNotice the difference in step #3.
I'm not familiar with GitExtensions, but here's what I think GitExtensions is doing: It is assuming that you want the given remote branch to be designated as the official upstream branch of the given local branch. With that assumption, creating origin/A
as a remote-tracking branch for the remote's develop
branch makes a moderate amount of sense. I'd be curious to know if GitExtensions also modifies the remote.origin.fetch
or branch.A.merge
configuration settings in .git/config
to really make the designation official. If so, it's poor user interface design. If not, then it's probably a bug.