In Git-config you can see:
branch.name.remote
When on branch <name>, it tells git fetch and git push which remote to fetch from/push to. The remote to push to may be overridden with remote.pushDefault (for all branches). The remote to push to, for the current branch, may be further overridden by branch.<name>.pushRemote. If no remote is configured, or if you are not on any branch, it defaults to origin for fetching and remote.pushDefault for pushing .
Now I have a cloned
repository and a branch which is named test
and is checkouted . Here you can see contents of config
file of the cloned repository:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = ...
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
As you see, branch.
test
.pushRemote
, remote.pushDefault
and branch.
test
.remote
are not set there. So I expect when I do
$ git push
I will get
fatal: No configured push destination.
But I get
Everything up-to-date
It seems Git
uses origin
instead of not configured remote.pushDefault
. But why when docs say
it defaults to remote.pushDefault for pushing .
Edit:
In Git-push you can see:
When the command line does not specify where to push with the <repository> argument, branch.*.remote configuration for the current branch is consulted to determine where to push. If the configuration is missing, it defaults to origin .
It think there is a conflict between using origin
and remote.pushDefault
.
If you look at the explenation for remote.pushDefault
:
remote.pushDefault
The remote to push to by default. Overrides branch. .remote for all branches, and is overridden by branch. .pushRemote for specific branches.
So it's meant for overriding the default remote when pushing. When it's not set, it does nothing, and the default remote of origin comes into play.
Note that remote.pushDefault
has been added later (v1.8.3), so it would break a lot of things when these semantics would change.
Git's push code (and pull too, really) is (in my opinion) unnecessarily complicated because it tries to retain a large number of historical behaviors, several of which were bad ideas.
Let's look first at the REMOTES section of the git-push
documentation :
The name of one of the following can be used instead of a URL as repository argument:
a remote in the Git configuration file:
$GIT_DIR/config
,a file in the
$GIT_DIR/remotes
directory, ora file in the
$GIT_DIR/branches
directory.All of these also allow you to omit the refspec from the command line because they each contain a refspec which git will use by default.
(The name of a remote is—again, this is just my opinion—the only one of these that really should survive today. I think the specified-URL method probably should be moved to a plumbing command, and git push
could return to being a simple script, although the Git-on-Windows folks are, alas, trying to convert away from scripts due to Windows performance issues.)
Fortunately, you are using the named-remote method, so we can ignore most of this. Specifically, the refspec is optional because you are using a remote in $GIT_DIR/config
.
Next, we should clearly distinguish between syntax (nouns and verbs and such that you enter on a command line) and semantics (behavior). Once we toss out the extra varieties of "remote" we're left with two tasks:
The syntax you used was git push
, ie, no specified repository
argument and no specified refspec
. So for step 1, selecting a remote, Git uses the paragraph you quoted in your edit: find the current branch—in this case, test
–and then look up branch.test.remote
. This is not configured (is "missing"), so Git falls back to using origin
.
(There's a bug in the quoted documentation paragraph, as it fails to mention branch. branch .pushRemote
, which in this case would be branch.test.pushRemote
. The correct sequence is (1) look for the branch-specific pushRemote; (2) look for the branch-specific remote; (3) look for remote.pushDefault
if Git version 1.8.3 or newer; (4) try the word origin
. This documentation bug is still in git 2.8.1.)
Since origin
is a valid remote name, step 1 succeeds and we move on to step 2, selecting a refspec. This part does not have you puzzled, but just for completeness:
When the command line does not specify what to push with
refspec ...
arguments or--all
,--mirror
,--tags
options, the command finds the defaultrefspec
by consultingremote.*.push
configuration, and if it is not found, honorspush.default
configuration to decide what to push (Seegit-config(1)
for the meaning ofpush.default
).
So in this case, Git looks for remote.origin.push
and, since that is not set, push.default
. If push.default
is not set, there is a "default default", which in Git prior to 2.0 was matching
and is now (Git 2.0 or newer) simple
. This default push.default
means that there is always a refspec.
The default remote-name origin
means that there is usually a remote. This fails only when there is no [remote "origin"]
section in your $GIT_DIR/config
.
The answer is not as simple as for fetching, because there is a list of fallbacks which need to be considered:
To get the remote programatically, see this question .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.