【问题标题】:git push, when it ask to set upstream and when it and does notgit push,当它要求设置上游以及何时不设置
【发布时间】:2019-07-28 19:02:35
【问题描述】:

我不太清楚为什么git push 会为这些分支显示两条不同的消息。创建这两个分支,一个有origin/master,另一个没有。

第一个:git checkout -b dev origin/master

D:\Source\Projects\dev -> origin\fortnight (dev -> origin)(fortnight@1.0.0)

git 推送

致命的:你的上游分支 当前分支与您当前分支的名称不匹配。到 推送到远程的上游分支,使用

git push origin HEAD:master

要推送到远程的同名分支,使用

git 推送源开发

要永久选择任一选项,请参阅 'git help 中的 push.default 配置”。

另外一个:git checkout -b uat

D:\Source\Projects\uat -> origin\fortnight (uat -> origin)

git 推送

fatal:当前分支 uat 没有上游分支。推动 当前分支并将远程设置为上游,使用

git push --set-upstream origin uat

【问题讨论】:

标签: git


【解决方案1】:

TL;DR

如果您的push.default 设置为simple(或未设置并默认为simple),git push 将:

  1. 要求您的分支有上游集。如果没有,您会收到消息fatal: The current branch <em>name</em> has no upstream branch ...
  2. 要求 upstream 名称匹配 - 减去 remote 部分,即 - 当前分支名称。也就是说,如果您的分支命名为xyz,则上游名称必须为origin/xyz,假设远程命名为origin

因此,如果您没有设置上游,则会收到错误 #1;如果你有一个上游集,但由于 push.default 设置,它不是 Git “喜欢”的集,你会得到错误 #2。

在您使用git checkout -b 的两种方式中,其中一种会创建上游设置,而另一种则不会。实际的上游设置是让push.default 抱怨的设置。

这里没有一个很好的简短答案,因为这些东西的历史——最初称为跟踪,现在称为设置上游,以及方法这个上游的东西与多个不同的 Git 命令中的每一个交互——很长,坦率地说有点无聊。 :-) 不幸的是,您至少需要了解一点,才能理解现代(2.0 或更高版本)Git 的工作方式。这是因为 Git 人员一直试图保持与 Git 1.5 的兼容性,尽管实际上没有人使用 Git 1.5(几乎没有人再使用 Git 1.7,甚至,2.0 之前的任何东西都已经过时了)。

在我深入研究之前,请记住git pull 实际上是两个 Git 命令合二为一。 git pull 所做的首先是运行 git fetch。然后,在 fetch 工作之后,它运行第二个 Git 命令,通常是git merge。单独讨论这些效果更好——push 的反面不是pull,而是fetch。正如我们将看到的那样,这是由于某种历史错误造成的。

漫长而无聊的历史,尽我所能缩短

要接近开头并且速度非常快,问题的根源在于:最初的 git pull 是一个非常简短的脚本:它运行了 git fetch,然后运行了 git merge,就是这样。获取和合并通常是您需要的基本操作,所以它就是这样做的。但是这个原始的git pull 命令是不够的,因为通常不是总是。该脚本有时也会破坏您自己的存储库,如果出现问题或您在错误的时间运行它(我至少遇到过一次这种情况)。

脚本经过多次调整——它变得更好了,尽管我被烧得足以学会避免它——最终从头开始重写。当前的git pull,从 Git 2.6.0 及更高版本开始,不再是 shell 脚本,并且可能不再破坏存储库。 :-)(我自己仍然很少使用它。)与此同时,git fetchgit pushgit status 都获得了新功能,所有这些东西都纠结在一起了。

所有这些调整和重写的最终结果是,今天,你的每一个分支——你的master、你的dev创建和你的任何其他分支 控件——允许有 no 上游或 one 上游。但是上游到底是什么,它有什么好处呢?为什么会收到这些不同的消息,一个抱怨上游名称不匹配,另一个抱怨没有上游?为什么这一切如此混乱和复杂?我们可以马上回答最后一部分:它很混乱而且很复杂,因为在这些功能的演变过程中所犯的每一个错误仍然受到支持,以防万一有人依赖它。

定义分支名称的upstream设置:序言

分支名称的上游在 Git 内部非常简单,但它被定义为两部分。这两个部分是一个remote——我们还没有定义——然后是一个在遥控器上有意义的名字。因此,在我们定义 upstream 之前,我们必须定义 remote

定义一个remote和对应的remote-tracking名称

当你第一次运行git clone 时,你必须给它一个 URL。回到糟糕的过去,您必须每次都给 Git 一个 URL,一遍又一遍。显然,重复输入相同的 URL 是愚蠢的。我们有一台计算机,为什么不让记住URL?

这是遥控器的主要工作。遥控器只是一个简短的、易于键入的字符串,例如origin。这会记住一个 URL:您现在可以 git fetch origingit push origin,并且您的 Git 使用字符串 remote.origin.url 作为小型数据库中的键来查找 URL。当然,如果origin 记住了一个 URL,它也可以为你记住更多的东西,所以你可以使用这个短名称设置更多的东西,Git 会自动设置一个超级重要的 /em> 给你。

查看您的.git/config 文件:例如,在文件查看器中查看它,或运行git config --local --list(或同时尝试两者)。请注意,您有一个:

[remote "origin"]
    url = ...

或:

remote.origin.url=...

在这里设置。这就是 Git 保存 URL 的地方。

这个网址是什么?如果您要使用浏览器或使用curl 或其他方式调用它,那么它可能需要您先进行身份验证/登录/ 无论如何,但最后,URL 是什么at另一个 Git 存储库。另一个 Git,作为 Git,有 its 分支。您可以通过该 URL 让您的 Git 调用 Git,就像拨打电话或发送短信一样。然后两个 Git 将进行对话。他们将进行的确切对话取决于您运行的 Git 命令,但您可以随时运行一个,它只是显示来自他们的 Git 的内容:

git ls-remote origin

这可能只显示一点点,也可能显示很多,这取决于他们要告诉您多少内容。这是在 Git 存储库中使用它的一个 sn-p 显示:

3034dab9ed6b11970a53099a7b3ca981f1461365        HEAD
98e06ded345450b3b07099d3ed1abf58fc95f5b6        refs/heads/maint
3034dab9ed6b11970a53099a7b3ca981f1461365        refs/heads/master
0f2c4a37fdba75d06ae7254c4b30ed7739985214        refs/heads/next
[snip]
213030c8af8ad9f9060cc264395817adb4ede44e        refs/tags/v2.2.3
441c4a40173fe1ee8a5c0094e587dfc47e2a6460        refs/tags/v2.2.3^{}
90141c859541f8daa08bdb0621c64cbd7dadbd8c        refs/tags/v2.20.0
5d826e972970a784bd7a7bdf587512510097b8c7        refs/tags/v2.20.0^{}
[snip]

基本上,git ls-remote 让你的 Git 询问他们的 Git:你有哪些分支和标签?它们对应的哈希 ID 是什么? 这就是这里溢出的内容。当您的 Git 调用他们的 Git 并从他们那里获取东西时,您的 Git 就会知道他们的分支名称。然后你的 Git 重命名这些分支名称:他们的 master 变成你的 origin/master。他们的maint 成为您的origin/maint。他们的next 变成了你的origin/next 这种更名——实际上非常灵活;此处的简单重命名只是默认设置——将origin/ 粘贴在他们的 名前,以便您可以将它们与您的 名区分开来。文字字符串origin/ 来自于您在设置遥控器时选择调用此origin

等等,我没有选择origin,Git 做到了!

嗯,是的——但这只是默认。如果你运行:

git clone -o boo <url>

你会得到一个克隆,而不是origin,它的遥控器是boo。您将拥有boo/master,而不是origin/master,依此类推。如果您没有选择覆盖origin,那么实际上您选择了使用origin

无论如何,这就是origin 的全部意义所在:它是远程的名称,它成为各种远程跟踪名称的前缀您的 Git 用来记住 他们的 Git 的 分支 名称,这是您最后一次让 Git 调用他们的 Git。

这些带有远程和远程跟踪名称的东西是大约 Git 1.5 版左右的新东西(1.5 之前的细节在时间的迷雾中丢失了;我自己直到 1.5 左右才开始使用 Git。一些东西,甚至可能是 1.6,而发行说明只能追溯到 Git 1.5.0.1)。在此之前,Git 根本没有遥控器,还有其他缩写 URL 的方法。这些其他方法仍然有效,但您应该使用遥控器和远程跟踪名称。它们要好得多

如果有origin/master,将master 链接到它是有意义的

假设您的 Git 调用了他们的 Git,而您的 Git 发现他们已经更新了他们的 master。如果您使用git fetch 进行此调用,您的 Git 不仅会看到更新,还会获取他们所做的新提交。您的 Git 将这些新提交存储在您的存储库中——而不会影响您现在正在做的任何事情,这有时至关重要! 运行git fetch总是安全的,因为这个“不要碰其他东西”的技巧——然后你的 Git 会更新你的 origin/master 以记住你刚刚从他们那里得到的提交。

如果您正在处理一些微妙的事情,例如进行合并,您可以暂时忽略此更新。但是,如果 / 当你处于一个很好的简单停止点,或者准备使用你从他们那里得到的新提交......好吧,现在是时候让你用 你的 master,基于他们对 他们的 master所做的事情。 这就是将origin/master 设置为master 的上游变得有用的地方。 所以这让我们回到设置上游的后半部分。

请注意,顺便说一句,当您使用 git fetch 时,很有可能(可能至少 80%)最终会希望使用刚引入的内容进行合并或变基。因此,使用将这两个操作组合成一个git pull。我还是没有,有三个原因:(1)我经常被烫伤,有不同的习惯; (2) 80%,甚至 90% 或 95%,仍然不是 100%; (3) 我真的喜欢在合并之前通过 fetch 检查进来的内容。 (也许原因 3 是原因 1 的一部分,但有时它会决定我是否使用mergerebase,而不仅仅是何时我合并了新的提交。)

定义分支名称的上游设置

您的分支的上游通常只是您在存储库中使用的远程跟踪名称,以记住提交他们——无论他们是谁——在他们的 Git,您的 Git 已通过 git fetch 复制。也就是说,你通常希望 Git 将 master 的上游设置为 origin/master

但是,正如我在开头提到的那样,上游实际上设置在两部分中。一种是将分支masterremote 设置设置为origin。另一种是将你的分支mastermerge设置设置为master

$ git config --local --list
[snip]
branch.master.remote=origin
branch.master.merge=refs/heads/master
[snip]

这两个设置使我的master 的上游成为我的origin/master。您可以尝试将其视为只是将远程和合并连接在一起,但实际上这并不完全奏效。1

您还可以将您的一个(本地)分支的上游设置为另一个(本地)分支!例如,我可以创建一个分支 zorg,它的上游是 master。如果我这样做,上面的git config 会说:

branch.zorg.remote=.
branch.zorg.merge=refs/heads/master

在这种情况下,上游不是./master,而只是master您应该使用前端命令git branch --set-upstream-to 隐藏所有这些关于设置的remotemerge 部分的怪异之处; git branch 确切知道如何组合所有内容,并处理使此配置也适用于古老 Git 的向后兼容性。

要查找某个分支的当前上游设置,请使用git branch -vvgit rev-parse --symbolic-full-name,例如:

$ git branch -vv
* master          9c9b961d7e [origin/master] The sixth batch
[snip]

方括号中的文字显示当前上游。

$ git rev-parse --symbolic-full-name master@{upstream}
refs/remotes/origin/master

这揭示了远程跟踪名称如何真正工作的更多细节:全名实际上是refs/remotes/origin/master,而你的主人的全名是refs/heads/master(注意heads而不是remotes/origin)。


1不只是特殊远程名称. 有问题,merge 设置也通过remote.<em>remote</em>.fetch 设置映射。这里的想法是,branch.<em>name</em>.merge 中列出的 merge 设置是分支的名称​​在远程上看到,所以如果您将它们的名称重新映射到不寻常的远程跟踪名称,您的 Git 会根据需要自动执行相同的映射。如果您确切地知道自己在做什么,可以在这两个设置上使用 git config 两次,以设置或获取任何特定分支的上游设置。不过,使用git branchgit rev-parse 要容易得多。


哇,好的,这就是上游 ...但是是什么?

在这里,所有的历史,以及那些历史错误,都重新回到了画面中。在过去的糟糕日子里,你只是跑了:

git pull <url> <branch>

它有输入长 URL 的烦人问题。所以这变得更短了:

git pull <remote> <branch>

remote 几乎总是只有origin。但是如果我们有一个上游设置,它列出了remote部分branch部分在内部,git pull 可以你!所以现在你可以运行了:

git pull

pull 脚本会找到当前分支名称(例如,master),然后获取 branch.master.remotebranch.master.merge 设置,然后自动运行相同的操作为git pull origin master

感谢所有的向后兼容性,所有这些仍然像以前一样工作,这是上游为您做的第一件事。它可以让你在没有参数的情况下运行git pullgit pull 要么直接运行 git fetch,然后运行 ​​git merge,要么从 Git 2.6 开始,使用代码 from git fetchgit merge,并自动从正确的 Git 获取,并与正确的提交合并。

同样,设置上游让你可以不带参数地运行git fetch:Git 查看当前分支,获取它的remote——它不需要整个上游,只需要远程——然后执行git fetch到正确的 URL。设置一个上游让你运行git mergegit rebase 也没有参数:Git 查看当前分支,找出上游——这一次它需要整个事情——然后执行git merge origin/mastergit rebase origin/master if /视情况而定。

因此,对于这四个相关的命令 —git fetchgit mergegit rebasegit pull — 设置上游意味着您不必在每个命令中输入那么多。真的差不多了。

注意git pull总是首先运行git fetch,但您可以选择让它运行git rebase第二,而不是让它运行git merge第二。在这两种情况下,上游设置仍然控制mergerebase 的参数,如果您运行缩短的命令。2


2如果你不使用你的上游——如果你输入git pull <em>remote</em> <em>branch</em>——第二个命令,不管它是什么,使用你从命名远程带来的提示提交,而不使用完全是上游设置。这涉及到一些复杂的细节,包括这样一个事实,再次出于向后兼容性的原因,git fetch 总是将其获取的所有内容写入一个名为.git/FETCH_HEAD 的特殊文件中。这可以追溯到远程跟踪名称发明之前,尽管它实际上对于一次性获取和使用操作仍然有用。


上游有什么好处,第 2 部分:git statusgit branch

如果你使用git branch -vvgit status,有时你会看到这样的注解:

[origin/master: ahead 1, behind 10]

或:

Your branch and 'origin/master' have diverged,
and have 1 and 10 different commits each, respectively.

这些计数——Git 通过检查您的分支及其上游可访问哪些提交来计算,这是另一个非常长的讨论;我将在这里引用Think Like (a) Git — 告诉您可能需要做什么样的工作才能将您的分支与其上游重新同步。为此,您的分支必须拥有上游。

上游有什么好处,第 3 部分:git push

git fetchgit mergegit rebase 和二选一的git pull 命令一样,git push可以完全不带参数运行。为了让它工作,Git 需要知道两件事:我在哪里调用另一个 Git?我要求他们设置什么分支名称?

同样,上游提供了两条信息。但是这里还有更多的历史错误使这变得复杂。这就是 push.default 设置的用武之地。

这里值得注意的是git fetchgit push 之间存在不对称性。当您使用 git fetch 让您的 Git 调用 origin 的 Git 时,您的 Git 会从他们那里获得一个列表,其中包含所有分支的所有。然后,您的 Git 可以通过使用他们的所有分支找到他们所有的新提交,并将所有这些 重命名 为您的 origin/* 远程跟踪名称。

这使得在任何时候运行git fetch 变得完全安全。您的 Git 不会干扰任何您的工作;它只会从他们那里获得新的提交和/或更新您的远程跟踪名称。 你的分支都不会受到影响!

但是,虽然 git push 是最接近 git fetch 的对立面的东西,但它在一个非常重要的方面是不同的。例如,当您运行git push origin master 时,您让您的 Git 调用他们的 Git,如果需要,为他们提供新的提交,然后以礼貌的请求结束此对话:其他 Git,请设置您的 @987654493 @ 以通过原始哈希 ID 识别相同的提交,作为我自己的 master 也就是说,您将 直接 弄乱他们的分支。那里没有远程跟踪名称——没有alice/master,没有bob/master,没有riki/master,只有一个master。如果他们接受您的请求,他们会立即更改他们的分支。

您可能会争辩说这与 git pull 所做的相反,因为 git pull (a) 获取然后 (b) 合并或变基,这会以某种方式改变您的分支。但是步骤 (b) 总是 会更改或尝试更改您的分支非破坏性。推送操作只有在快进操作(同样我们没有定义,我不会在这里)。没有可用的合并或变基:只允许快进。您实际上可以运行 git fetch 在您自己的分支上执行快速转发,而不是更新您的远程跟踪名称;如果你这样做了,你会做 fetch 和 push 到真正的对立面(但是有更多的皱纹,我不想在这里详细说明)。

无论如何,这现在又回到了历史和兼容性——以及一种导致 Git 从 1.9 版到 2.0 版而不是 1.10 版的“重大变化”(注意当前的 Git 是 2.22 版,远远超过dot-10 版本)。

在 Git 版本 2.0 之前,git push origin,没有额外的参数,默认让你的 Git 在 origin 调用另一个 Git 并获取其所有分支的列表,就像 git ls-remotegit fetch 会做。 Git 当时的做法很聪明,但事实证明,另一个错误是:您的 Git 会将 您的 分支名称与 它们的 分支名称进行匹配。如果你有一个master 而他们有一个master,Git 会将master 添加到它的列表中。如果你有一个dev 而他们有一个dev,Git 会将dev 添加到它的列表中。匹配完你所有的名字后,你的 Git 会询问(默认礼貌,或强制使用--force)他们的 Git 设置 all 这些匹配的分支名称,基于 all 的分支名称。

这意味着如果他们——origin——有一个dev,然后你从你的master 中创建了自己的不同dev,然后运行git push origin 而没有具体命名任何东西,你的 Git 会要求他们的 Git 设置 他们的 dev 以匹配你的 dev即使你的 dev 与他们的 dev 无关 >.

在这种行为烧毁了太多 Git 初学者之后,Git 人决定改变它。他们添加了许多新方法来让git push 表现良好。他们创建了一个 git 配置设置,push.default,您可以设置它。一种设置称为matching:这就是 Git 1.x 默认所做的。新的“安全”设置称为simple:这就是 Git 2.x 默认所做的。

在很长的过渡期内,如果您没有自己设置 push.defaultgit push 会抱怨,告诉您 Git 1.x 与 Git 2.x 中的默认行为/将会有所不同。如果你经历过这种转变——或者仍在使用非常古老的 Git——你会看到这些抱怨,甚至可能已经设置了 push.default 设置。

现代 Git 不再抱怨;它默认使用simplesimple 设置要求您有两个名称匹配的上游集 。如果您从您的dev 推送,您必须推送到他们的 dev。如果您从您的master 推送,您必须推送到他们的 master

请注意,所有这些限制在您以方便的快捷方式运行 git push 时适用,您可以让上游设置告诉 Git 要推送什么和在哪里。如果你运行,比如说,git push origin master,你覆盖当前分支、上游和所有其他东西:你告诉你的 Git 调用他们的 Git 并要求他们设置他们的master 基于您的 master,即使您目前是自己的 dev

新分支与上游

当然,您可以创建一个 new 分支,它还没有上游,使用类似:

git checkout -b foo

或:

git branch foo

或:

git checkout -b foo origin/master

或:

git branch foo origin/master

甚至:

git checkout -b foo master

等等。

有很多方法可以创建分支。当您创建一个新分支时,您可以选择让新分支立即具有上游设置,如果您使用其他分支名称来创建它。 provided 部分的原因是上游是另一个分支的名称。如果你创建一个分支而不使用其他名称,Git 会使用什么其他名称?

好的,但是这里有一个非常棘手的地方。实际上,有几个棘手的地方——我认为其中一些是历史性的,而一些只是 Git 是非常可配置的事实。首先,考虑一下 Git 所说的 DWIM(按我的意思做)。假设您刚刚克隆了一个存储库,并且在您的master 上,但origin 存储库有masterdevfeature/shortfeature/tall。您现在可以运行:

git checkout feature/short

例如,即使您没有feature/short。这会调用 Git 的“DWIM 模式”:Git 看到您确实拥有origin/feature/short,并将其转换为:

git checkout -b feature/short --track origin/feature/short

这个--track 选项使用旧的(坏的)动词,意思是设置上游。这将创建feature/short 分支将其上游设置为origin/feature/short

同样的技术适用于所有其他分支名称,事实上,git clone 首先是您的master。在git clone 进程结束时,您的Git 实际上运行git checkout master。你没有一个主人,但你确实有一个origin/master。因此,您的 Git 制作您的 master 将其上游设置为 origin/master,作为 git clone 的最后一步。

如果你使用:

git branch name start-point-name

您的 Git 会经常(但并非总是)使用 start-point-namename 设置上游。您可以使用branch.autoSetupMergebranch.autoSetupRebase 选项进行配置。第一个具有三个可能的值:falsetruealways,用于 branch.autoSetupMerge。第二个有四个:neverlocalremotealways 用于branch.autoSetupRebase。这些在the git config documentation 中得到了合理完整的描述。

其中一些自动设置的上游名称满足git pushsimple 设置,而有些则不满足。 “DWIM 模式”总是这样,所以特别方便。

另一个 Git 中没有对应名称的新分支

假设你这样做:

git checkout -b dev

要在你自己的 Git 中创建一个新分支 dev并且在他们的 Git 中没有 dev,在 origin。您可能想将dev 的上游设置为origin/dev,因此您的下一个命令是:

git branch --set-upstream-to origin/dev

会发生这样的事情:

$ git checkout -b dev
Switched to a new branch 'dev'
$ git branch --set-upstream-to origin/dev
error: the requested upstream branch 'origin/dev' does not exist
hint: 
[snip]

稍后我将展示其余的提示,但这里的要点应该足够清楚:origin 没有 dev,所以我们 em> 没有origin/dev。因此,我们不能将dev 的上游设置为我们的origin/dev

我们必须做的——好吧,无论如何我们应该做的明智的选择——是:如果我们愿意,继续做一些工作,很快——甚至可能是现在—— 要求他们的 Git 根据我们的 dev 创建他们的 dev。一旦他们创建了dev,我们的Git 就会在我们的存储库中创建我们的origin/dev。然后我们就有了一个可以--set-upstream-to的名字。

所以,这是hint 输出的其余部分:

hint: If you are planning on basing your work on an upstream
hint: branch that already exists at the remote, you may need to
hint: run "git fetch" to retrieve it.
hint: 
hint: If you are planning to push out a new local branch that
hint: will track its remote counterpart, you may want to use
hint: "git push -u" to set the upstream config as you push.

git push -u 的推荐只是一条捷径。我们现在可以运行了:

git push origin dev

这将立即在他们的系统上创建一个dev,匹配我们的dev(指向相同的提交哈希)。然后我们就可以运行了:

git branch --set-upstream-to origin/dev

但如果我们可以让我们的 Git同时执行这两个操作,那可能会很好,这就是 git push -u 所做的:

git push -u origin dev

让我们的 Git 调用他们的 Git,让他们根据我们的 dev 创建一个新的 dev,然后——如果成功——也执行一个 git branch --set-upstream-to

您只必须执行一次此操作,即便如此,也只有在您使用各种push.default 设置中的一些 时。如果您愿意,可以更频繁地使用-u 选项:它只会继续运行额外的git branch --set-upstream-to。如果您的分支已经有上游,您将重新设置它:如果没有更改,则重新设置是无害的。如果您的分支没有上游,您将设置它:现在您有一个上游。似乎-u 应该是默认值,不是吗?但这不会向后兼容:git push 之前没有设置上游,所以现在也没有。

还有大量额外的配置选项

您可以设置更多配置选项,这些选项会影响git fetchgit pushgit pull 等。例如,您可以从一个远程获取并自动推送到另一个远程或 same 远程的不同 URL,这可能仅在您能够在不进行身份验证的情况下获取但可以仅使用身份验证推送并且身份验证由于某种原因很慢或很痛苦。

其中一些选项会影响 为什么 git push -u 也不是默认值。在大多数情况下,考虑到 Git 面临的向后兼容性限制,大多数这些东西都已尽可能地设置好。如果您发现 Git 的某些方面令人讨厌,请检查是否有配置可以解决此问题,因为经常有 。例如,在这种特殊情况下,您可以更改您的push.default。但也要考虑到,在某些情况下——包括这个——默认值是通过痛苦的经历得出的,有点像我避免使用git pull 的方式。 :-)

【讨论】:

  • 这是一个了不起的答案。谢谢@torek。
猜你喜欢
  • 2013-07-24
  • 2015-09-23
  • 1970-01-01
  • 2011-12-31
  • 2017-02-15
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多