Grofit Grofit - 25 days ago 8
Git Question

git bash cloning incorrect url with Visual Studio Team Services (VSTS)

I have a really weird issue with one of the guys in the office here where we moved on of the repos from one project in TFS into another (I will use TFS here but I mean Visual Studio Team Services, which is basically TFS in the cloud).

So our repo used to live somewhere like:

https://somewhere.visualstudio.com/projects/_git/something


Then it was copied to another project and the old one removed, so it now lives at:

https://somewhere.visualstudio.com/project_two/_git/something


When one of the guys here tries to clone from the new repo url:

git clone https://somewhere.visualstudio.com/project_two/_git/something


He gets the error:


remote: TF401019: The Git repository with name or identifier something
does not exist or you do not have permissions for the operation you
are attempting. fatal: repository
'https://somewhere.visualstudio.com/projects/_git/something' not found


Its like there is some cache somewhere which seems to be redirecting the new repo url to the old one, which no longer exists. It doesn't happen for me on my computer.

So is there anything behind the scenes in GIT which would cause this repo url to be cached somewhere, or anything in TFS which would cause this behavior?

== Verbose Output ==

somename@cf-l-003242 MINGW64 /d/Repos
$ GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://somewhere.visualstudio.com/project_two/_git/something
10:50:02.761600 git.c:349 trace: built-in: git 'clone' 'https://somewhere.visualstudio.com/project_two/_git/something'
Cloning into 'something'...
10:50:02.801600 run-command.c:336 trace: run_command: 'git-remote-https' 'origin' 'https://somewhere.visualstudio.com/projects/_git/something'


So it looks like the origin is messed up, however he has uninstalled and re-installed git and is cloning a repo to a new folder so I don't know why it would mess up the origin.

tom tom
Answer

Solution

The problem was that the global Git configuration file (~/.gitconfig) had a configuration for origin:

[remote "origin"]
    url = https://somewhere.visualstudio.com/projects/_git/something

Deleting this section fixed things.

Explanation

Git uses configuration files to store both user preferences and repository information. Each repository has its own configuration file (.git/config in the repository directory), and there is also a global configuration file ~/.gitconfig.

The command git config can modify these files. It modifies the repository configuration file by default, and has a flag --global to modify the global configuration file. The files can also be edited using a text editor.

Usually, user preferences are stored in the global configuration file and repository information is stored in the per-repository file. This doesn't have to be the case though.

For example, my full name and email address are stored in my global configuration file. If I want to use a different email address when working in a particular repository, I can set the email address in that repository's configuration file.

Conversely, repository information can be stored in the global configuration file to provide default values for all the repositories. This can have unexpected consequences. In particular, if the URL of origin is set globally using

git config --global remote.origin.url https://xyz  # WARNING: Causes weirdness

then any attempt to clone a repository over HTTP(S) or SSH will result in https://xyz being fetched, regardless of the URL specified in the command line (tested with Git 1.7.9.5 and Git 2.10.2).

To fix this, open ~/.gitconfig using a text editor and delete options that shouldn't be global. Make a backup first, and refer to git help config if you aren't sure what an option does.

Debugging Notes

Here are the steps I used to discover the problem's cause.

The output from

GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone ...

showed that the URL was correct in line 349 of git.c but wrong in line 336 of run-command.c. I decided to run Git in a debugger (gdb) and see what happened between those two points.

I compiled the latest version of Git from source to get debugging symbols. The line numbers in the question matched in the version I downloaded, which was convenient (getting the same version of Git would have been even better).

When I stepped through the code I noticed a call to remote_get() in line 991 of builtin/clone.c. This function reads the configuration, which seemed like a place where a new URL could emerge. I set remote.origin.url globally, and successfully replicated the behaviour in the question.

Compiling Git from source and stepping through in a debugger is not something an average user is expected to do. Another experienced Git user might have immediately suspected the global configuration file, since it survives re-installations.

Comments