35

When I try to create a new branch tracking a remote branch, I get this:

$ git branch -t test origin/foo
error: Not tracking: ambiguous information for ref refs/remotes/origin/foo

The source seems to somehow search for branches to track and throws me out because it finds less more than one, but I don't exactly get what it's looking for since I already told it what to track on the command line.

Can anybody tell me what's going on and how to fix it?

che
  • 12,097
  • 7
  • 42
  • 71
  • Just added some terminology, and some suggestions (just leads to explore, nothing definitive though) to explain the current situation. – VonC Sep 08 '09 at 21:51
  • Thank you for the feedback, but did you actually found the reason behind your error message? – VonC Sep 09 '09 at 16:45

5 Answers5

44

I saw this also when I had two remote repo's with the same (default) fetch pattern (fetch = +refs/heads/*:refs/remotes/origin/*) and the same branches.

The original mistake was in creating two remotes with the same fetch configuration. The new remote has a different name, and therefore the name of its folder should have been changed as well. Here is an example of a proper multiple-remote configuration:

[remote "origin"]
    url = <primary-source>
    fetch = +refs/heads/*:refs/remotes/origin/*
[remote "alt"]
    url = <alternate-source>
    fetch = +refs/heads/*:refs/remotes/alt/*

In place of alt put any name of your choosing.

Explanation:

The meaning of refs/heads/*:refs/remotes/origin/* is: take all the remote reference in refs/heads on the remote side, and put the to refs/heads/origin on our side. refs/heads is the path where branches are stored, so if you have branch foo on the remote, it will be fetched to origin/foo in your local repo. The + on the beginning means that the destination branches should be always overwritten (w/o that there are some additional checks).

Alternatively:

You can also manually add the info to the project's .git/config, e.g.:

[branch "mybranch"]
    remote = origin
    merge = refs/heads/mybranch
Neil Traft
  • 18,367
  • 15
  • 63
  • 70
Matthew Phillips
  • 1,275
  • 1
  • 12
  • 19
  • 13
    I guess the fix would be to have different remotes fetch to different places, eg. instead of both having `fetch = +refs/heads/*:refs/remotes/origin/*`, try to rename the second destination to something like `fetch = +refs/heads/*:refs/remotes/another_repo/*`. – che Mar 25 '10 at 17:10
  • A very good point -- the reference to origin in the second repo doesn't seem right. I really need to go away and fully understand what the "fetch" lines really mean, so I can configure the second repo (which is essentially a mirror) properly. – Matthew Phillips Mar 26 '10 at 01:49
  • 6
    The meaning of `refs/heads/*:refs/remotes/origin/*` is: take all the remote reference in `refs/heads` on the remote side, and put the to `refs/heads/origin` on our side. `refs/heads` is the path where branches are stored, so if you have branch `foo` on the remote, it will be fetched to `origin/foo` in your local repo. The `+` on the beginning means that the destination branches should be always overwritten (w/o that there are some additional checks). – che Mar 27 '10 at 01:01
  • Thanks for that, that really helps. I was totally misreading what that meant. – Matthew Phillips Mar 31 '10 at 04:55
  • @che This really helped me. Having two remotes with the same place to put tags overwrote those every time because of this. Maybe you should make your own answer :) – Sylwester Mar 04 '13 at 12:59
  • @Sylwester: I can't make an answer if I don't know the question :-) You can help others by writing up your problem as a question and then answering it yourself with the information you just found. – che Mar 05 '13 at 11:36
  • @MatthewPhillips Thank you! I was having this problem and this explained it. After getting rid of the second remote (now unused, anyway) I am able to assign upstreams normally again. – molecule Feb 22 '17 at 19:36
17

because it finds less than one

Nope: because it finds more than one matching remote branch, which means the function remote_find_tracking() returns more than one tracking branch for a given local branch ref.

Is some_remote_branch not already tracked by one of your local branches?
(a git config -l would allow you to check what you have currently have set up).
(a git branch -r can also help to list your current remote-tracking branches. )

See also "copy a branch from one to another repo" for more details with Git 2.36 (Q2 2022).


remote branches, which I thought are something different that remote-tracking branches.

Wrong, as illustrated by this thread:

remote-branches are the "real" remote-tracking-branches. You don't commit to them locally, they are essentially read-only copies of exactly what is happening in a remote repository.
If you try to 'git-checkout' a remote-tracking branch, you will get a detached HEAD.

Local branch:
A branch to which you may commit changes. Optionally, the branch can be configured to "follow" one of your remote-tracking branches. This means that a 'git-pull' without arguments (when your local branch is checked out), will automatically 'git-fetch' and then 'git-merge' the remote-tracking branch.

Now:

it's the job of git-fetch to update remote-tracking branches with any changes found in the remote repository.
Git-pull runs git-fetch and then runs a git-merge to update the currently-checked-out branch.

The problem is, for git-merge:

When this happens, git-merge must decide which remote-tracking-branch to merge into the currently checked out local branch.
You can set which remote-tracking-branch will be selected in this situation with the --track option.

--track sets up a local following branch to refer to a remote's branch, not to the tracking branch

Consider that remote_find_tracking() takes a single remote and a refspec with src filled, and returns the given refspec after filling its dst, if an appropriate tracking was configured for the remote, meaning git.

/*
 * For the given remote, reads the refspec's src and sets the other fields.
 */
int remote_find_tracking(struct remote *remote, struct refspec *refspec);

May be it considers it already has a local following branch matching some_remote_branch. Do you have any local branch with that exact same name?
Or, the other way around: your current branch has a remote branch with a similar name, which makes it a natural candidate for any git-merge: trying to make it track another remote branch would make the git-merge unable to choose which local branch to update/merge with changes of a remote.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • I managed to write exactly the opposite of "more", thanks for pointing that out :-) Anyway, I seem to get the message even if I try to set up local branch from a remote branch that I just got by git-fetch. git config -l does not contain anything familiar to the remote branch, and git branch -r just lists remote branches, which I thought are something different that remote-tracking branches. Or am I confusing stuff? – che Sep 08 '09 at 21:04
  • 1
    Thanks for detailed reply, as I'm reading it I guess the main problem was that I didn't quite know what I was doing. – che Sep 09 '09 at 16:18
  • Thanks for the detailed answer. It helped me figure out that my problem was caused by having 2 remotes with the same fetch pattern. – dregad Jun 12 '16 at 08:50
13

Got it! The problem was that I have previously set up a remote with --mirror, for the purpose of having a backup / public copy of my repository.

If you run

git remote add --mirror <name> <url>

it does not only flag the remote as mirror (which is what I wanted for pushes), but also configures remote.<mirror>.fetch option for the mirror to +refs/*:refs/*, which means that all of your branches suddenly "track" your mirror repository and any attempt to create a tracking branch is going to fail.

(As an added bonus, running git fetch <mirror> is going to overwrite all your refs with old ones from your backup repo.)

The solution that seems to fix this issue is setting remote.<mirror>.fetch to : (which, I hope, means "never fetch anything"). This apparently fixes the tracking issue and eliminates the deadly fetch.

che
  • 12,097
  • 7
  • 42
  • 71
5

None of the other fixes mentioned here worked for me. The one that ended up working was this:

$ git branch -t test origin/test
error: Not tracking: ambiguous information for ref refs/remotes/origin/test

After running the above, even though git complained, it did end up creating a local branch test but no upstream set.

Now, I opened the .git/config file (which did not have any record of a branch test) and added the following manually:

[branch "test"]
        remote = origin
        merge = refs/heads/test

After which everything worked fine.

GuSuku
  • 1,371
  • 1
  • 14
  • 30
2

I got in a situation like this, but I do not know how. The listing from git branch -av showed me only a single remote tracking branch for the branch I cared about (origin/dev).

What I did to fix it was to use the hexadecimal commit hash instead of origin/dev:

git checkout -b dev abc123
git push -u origin dev

When I did the push with -u Git said Branch dev set up to track remote branch dev from origin. Subsequent pulls and pushes worked as I expected.

amacleod
  • 1,450
  • 2
  • 15
  • 23