Number945
Number945

Reputation: 4940

git push not asking to set upstream even though upstream not set

I have master branch and I have the following configurations set.

branch.master.remote=github
branch.master.merge=refs/heads/master
push.default=simple

Now I wanted to test behaviour of push.default. I did

git branch master1 // This created a new branch on same commit as master
git checkout master1
git push github

Now, since my local branch name is master1 and it is new branch , it does not have any upstream set with it. Why did not git push github showed me error message to use --set-upstream flag ? Also, it successfully created master1 branch on remote repo. Also, I see no remote tracking branch with it upon running git branch -vv

  master  42f18f8 [github/master] Some message
  master1 42f18f8 Some message

However, if I had just done git push while being on master1 branch , then it asks for --set-upstream.

Also, I dont have remote.github.push or remote.master1.push set.

Upvotes: 0

Views: 359

Answers (2)

torek
torek

Reputation: 488471

Let's take this in two parts.

git push and upstreams

First: git push, with no additional arguments, will (usually—depending on settings, which I won't go into here), looks at the upstream setting of the current branch.

If there isn't an upstream on the current branch, you get:

fatal: The current branch <branch> has no upstream branch.

(followed by configurable advice to use git push --set-upstream; if you configure it away, you won't get the advice).

If there is an upstream, you don't get that error. That's all there really is to it. If there is an upstream set, git push won't tell you to set one. If not, it will give you an error, and (unless you've configured the advice away) suggest that you set one.

Second, git push with additional arguments behaves differently. Edit: the next bit was wrong. The crucial additional argument here was the github argument. See jthill's answer for details. I've left the rest in strikeout because it can apply in some situations as well.

But you did not run:

git push github

You actually ran:

git push github master1

(Check your command history.) If you supply a refspec argument, which this four-word git push command does, the refspec supplies the branch names—both the one used locally, and the one your Git requests that their Git set. There's no need for the current branch, nor for any upstream settings of any branches.

git branch or git checkout -b and upstreams

Both git branch and git checkout can create new branch names.

A branch name can have an upstream set, or not set.

Therefore, when git branch or git checkout creates a new branch name, they have the option of setting an upstream.

Their actual behavior is configurable, using branch.autoSetupMerge and branch.autoSetupRebase. Their default behavior, though, is this:

  • If you don't supply a starting commit, use HEAD as the starting commit when creating the new branch, and do not set an upstream.
  • If you do supply a starting commit, check the form of the supplied argument:
    • If it has the form of a remote-tracking name—which implies both the remote and the branch name as seen on that remote—set an upstream.
    • Otherwise, don't set an upstream.

Since git branch master1 does not supply a starting commit, the new name is created using the hash ID to which HEAD resolves, and it has no upstream. Hence your git branch -vv showed no upstream set.

Settings make things complicated

The exact details of all of the possible interactions between all the different settings (push.default, remote.<name>.push, and others) can mess with all of this. I mention this primarily because you mentioned that you have not set any of these. If you do, some or all of the above may be invalidated. The Git documentation covers some, but not all possible, combinations.

Where it says that some combination is supposed to behave in some particular manner, it should behave that way. Otherwise, it may behave in any way the Git coders felt was convenient for them. Be careful when configuring options: some combinations have probably never been tested.

Upvotes: 0

jthill
jthill

Reputation: 60305

I think you missed the second paragraph of the simple docs:

When pushing to a remote that is different from the remote you normally pull from, work as current. This is the safest option and is suited for beginners.

and you're pushing to a remote that is not the remote you normally pull from. So it works as "current", "push the current branch to update a branch with the same name on the receiving end".

Git's trying to avoid newbies doing unintentional damage while still being as helpful as possible, exactly what needs to be allowed or prevented by default is always going to be a bit befuddling because rookie mistakes are too.

Upvotes: 2

Related Questions