Git 推送的默认远程

Default remote for Git push

Git-config中可以看到:

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.

现在我有一个 cloned 存储库和一个名为 test 的分支,并且 已检出 。在这里您可以看到克隆存储库的 config 文件的内容:

[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

如您所见,branch.test.pushRemoteremote.pushDefaultbranch.test.remote 没有在那里设置。所以我希望我什么时候做

$ git push

我会得到

fatal: No configured push destination.

但是我明白了

Everything up-to-date

似乎 Git 使用 origin 而不是未配置 remote.pushDefault。但是为什么当文档说

it defaults to remote.pushDefault for pushing.

编辑:

Git-push中可以看到:

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.

它认为使用 originremote.pushDefault 之间存在冲突。

如果您查看 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.

所以这意味着在推送时覆盖 默认遥控器。未设置时,它什么都不做,默认的 origin 遥控器开始起作用。

请注意,remote.pushDefault 是后来添加的 (v1.8.3),因此当这些语义发生变化时会破坏很多东西。

Git 的推送代码(实际上也包括拉取代码)(在我看来)过于复杂,因为它试图保留大量历史行为,其中一些是糟糕的想法。

我们先来看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, or

  • a 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.

(遥控器的名称——再一次,这只是我的意见——其中唯一真正应该保留至今的名称。我认为指定的-URL 方法可能应该移至管道命令,git push 可以 return 成为一个简单的脚本,尽管 Git-on-Windows 的人,唉,试图将 转换为 [= =79=] 由于 Windows 性能问题来自脚本。)

幸运的是,您使用的是 named-remote 方法,因此我们可以忽略其中的大部分内容。具体来说,refspec 是可选的,因为您在 $GIT_DIR/config.

中使用遥控器

接下来,我们应该清楚地区分语法(名词和动词以及您在命令行中输入的内容)和语义(行为)。一旦我们扔掉了 "remote" 的额外变体,我们就剩下两个任务:

  1. Select一个遥控器。
  2. Select 参考规范。

您使用的语法git push,即没有指定repository参数,也没有指定refspec。因此,对于第 1 步,选择一个遥控器,Git 使用您在编辑中引用的段落:找到当前分支——在本例中,test——然后查找 branch.test.remote。这未配置(是 "missing"),因此 Git 退回到使用 origin.

(引用的文档段落中有一个错误,因为它没有提到 branch.<em>branch</em>.pushRemote,在这种情况下将是 branch.test.pushRemote。正确的顺序是 (1) 查找特定于分支的 pushRemote;(2) 查找特定于分支的远程;(3) 如果 Git 则查找 remote.pushDefault版本 1.8.3 或更新版本;(4) 尝试 origin 这个词。此文档错误仍在 git 2.8.1.)

因为 origin 一个有效的远程名称,第 1 步成功,我们继续第 2 步,选择一个 refspec。这部分没有你疑惑,只是为了完整性:

When the command line does not specify what to push with refspec ... arguments or --all, --mirror, --tags options, the command finds the default refspec by consulting remote.*.push configuration, and if it is not found, honors push.default configuration to decide what to push (See git-config(1) for the meaning of push.default).

所以在这种情况下,Git 查找 remote.origin.push,并且由于未设置,所以 push.default。如果未设置 push.default,则有一个 "default default",在 2.0 之前的 Git 中是 matching,现在是(Git 2.0 或更新版本)simple。这个默认 push.default 意味着 总是 一个 refspec.

默认的遥控器名称origin意味着通常一个遥控器。仅当 $GIT_DIR/config.

中没有 [remote "origin"] 部分时才会失败

答案不像获取那么简单,因为有一个需要考虑的回退列表:

要以编程方式获取遥控器,请参阅 this question