Why call git branch --unset-upstream to fixup?

git, git-branch, github-pages

Solution

TL;DR version: remote-tracking branch `origin/master` used to exist, but does not now, so local branch `source` is tracking something that does not exist, which is suspicious at best—it means a different Git feature is unable to do anything for you—and Git is warning you about it. You have been getting along just fine without having the "upstream tracking" feature work as intended, so it's up to you whether to change anything.

For another take on upstream settings, see Why do I have to "git push --set-upstream origin <branch>"?

This warning is a new thing in Git, appearing first in Git 1.8.5. The release notes contain just one short bullet-item about it:

- "git branch -v -v" (and "git status") did not distinguish among a branch that is not based on any other branch, a branch that is in sync with its upstream branch, and a branch that is configured with an upstream branch that no longer exists.

To describe what it means, you first need to know about "remotes", "remote-tracking branches", and how Git handles "tracking an upstream". (Remote-tracking branches is a terribly flawed term—I've started using remote-tracking names instead, which I think is a slight improvement. Below, though, I'll use "remote-tracking branch" for consistency with Git documentation.)

Each "remote" is simply a name, like `origin` or `octopress` in this case. Their purpose is to record things like the full URL of the places from which you `git fetch` or `git pull` updates. When you use `git fetch remote,`1 Git goes to that remote (using the saved URL) and brings over the appropriate set of updates. It also records the updates, using "remote-tracking branches".

A "remote-tracking branch" (or remote-tracking name) is simply a recording of a branch name as-last-seen on some "remote". Each remote is itself a Git repository, so it has branches. The branches on remote "origin" are recorded in your local repository under `remotes/origin/`. The text you showed says that there's a branch named `source` on `origin`, and branches named `2.1`, `linklog`, and so on on `octopress`.

(A "normal" or "local" branch, of course, is just a branch-name that you have created in your own repository.)

Last, you can set up a (local) branch to "track" a "remote-tracking branch". Once local branch `L` is set to track remote-tracking branch `R`, Git will call `R` its "upstream" and tell you whether you're "ahead" and/or "behind" the upstream (in terms of commits). It's normal (even recommend-able) for the local branch and remote-tracking branches to use the same name (except for the remote prefix part), like `source` and `origin/source`, but that's not actually necessary.

And in this case, that's not happening. You have a local branch `source` tracking a remote-tracking branch `origin/master`.

You're not supposed to need to know the exact mechanics of how Git sets up a local branch to track a remote one, but they are relevant below, so I'll show how this works. We start with your local branch name, `source`. There are two configuration entries using this name, spelled `branch.source.remote` and `branch.source.merge`. From the output you showed, it's clear that these are both set, so that you'd see the following if you ran the given commands:

$ git config --get branch.source.remote
origin
$ git config --get branch.source.merge
refs/heads/master

Putting these together,2 this tells Git that your branch `source` tracks your "remote-tracking branch", `origin/master`.

But now look at the output of `git branch -a`, which shows all the local and remote-tracking branch names in your repository. The remote-tracking names are listed under `remotes/` ... and there is no `remotes/origin/master`. Presumably there was, at one time, but it's gone now.

Git is telling you that you can remove the tracking information with `--unset-upstream`. This will clear out both `branch.source.origin` and `branch.source.merge`, and stop the warning.

It seems fairly likely that what you want, though, is to switch from tracking `origin/master`, to tracking something else: probably `origin/source`, but maybe one of the `octopress/` names.

You can do this with `git branch --set-upstream-to`,3 e.g.:

$ git branch --set-upstream-to=origin/source

(assuming you're still on branch "source", and that `origin/source` is the upstream you want—there is no way for me to tell which one, if any, you actually want, though).

(See also How do you make an existing Git branch track a remote branch?)

I think the way you got here is that when you first did a `git clone`, the thing you cloned-from had a branch `master`. You also had a branch `master`, which was set to track `origin/master` (this is a normal, standard setup for git). This meant you had `branch.master.remote` and `branch.master.merge` set, to `origin` and `refs/heads/master`. But then your `origin` remote changed its name from `master` to `source`. To match, I believe you also changed your local name from `master` to `source`. This changed the names of your settings, from `branch.master.remote` to `branch.source.remote` and from `branch.master.merge` to `branch.source.merge` ... but it left the old values, so `branch.source.merge` was now wrong.

It was at this point that the "upstream" linkage broke, but in Git versions older than 1.8.5, Git never noticed the broken setting. Now that you have 1.8.5, it's pointing this out.

That covers most of the questions, but not the "do I need to fix it" one. It's likely that you have been working around the broken-ness for years now, by doing `git pull remote branch` (e.g., `git pull origin source`). If you keep doing that, it will keep working around the problem—so, no, you don't need to fix it. If you like, you can use `--unset-upstream` to remove the upstream and stop the complaints, and not have local branch `source` marked as having any upstream at all.

The point of having an upstream is to make various operations more convenient. For instance, `git fetch` followed by `git merge` will generally "do the right thing" if the upstream is set correctly, and `git status` after `git fetch` will tell you whether your repo matches the upstream one, for that branch.

If you want the convenience, re-set the upstream.

1`git pull` uses `git fetch`, and as of Git 1.8.4, this (finally!) also updates the "remote-tracking branch" information. In older versions of Git, the updates did not get recorded in remote-tracking branches with `git pull`, only with `git fetch`. Since your Git must be at least version 1.8.5 this is not an issue for you.

2Well, this plus a configuration line I'm deliberately ignoring that is found under `remote.origin.fetch`. Git has to map the "merge" name to figure out that the full local name for the remote-branch is `refs/remotes/origin/master`. The mapping almost always works just like this, though, so it's predictable that `master` goes to `origin/master`.

3Or, with `git config`. If you just want to set the upstream to `origin/source` the only part that has to change is `branch.source.merge`, and `git config branch.source.merge refs/heads/source` would do it. But `--set-upstream-to` says what you want done, rather than making you go do it yourself manually, so that's a "better way".

Problem

I'm more of a novice when it comes to advanced operations in git. I maintain my blog using the blogging framework Octopress. Though Octopress is not under any development since 2011, it serves my purpose well and so I haven't thought of changing anything so far. FYI, my blog is hosted on Github Pages. Today, while working on a new post, `git status` showed the following message: ``` On branch source Your branch is based on 'origin/master', but the upstream is gone. (use "git branch --unset-upstream" to fixup) ``` The same message repeated for all the subsequent commands such as `git add .`, `git commit -m 'message'` and `git push origin source`. - What does the message mean? - Is something broken? - If yes, what? - Do I need to fix it? If possible, please point me to a pdf/web article where I can read up on this and understand it for future. More details: ``` bash-3.2$ git branch -a * source remotes/octopress/2.1 remotes/octopress/HEAD -> octopress/master remotes/octopress/gh-pages remotes/octopress/linklog remotes/octopress/master remotes/octopress/refactor_with_tests remotes/octopress/rubygemcli remotes/octopress/site remotes/origin/source ``` Please let me know if more information is needed. Thanks.

Original source

Related problems