如何clone,然后sync/update/push与上游master fork
How to clone, then sync/update/push a fork with the upstream master
我想我已经通读了一些教程,但我仍然停留在一些完全基础的东西上(我几乎从不使用命令行 git,所以请耐心等待 ;))。
我只想从上游仓库更新我的叉子 (https://github.com/abelbraaksma/visualfsharp) to the latest version of Master (https://github.com/Microsoft/visualfsharp)。由于我有一些我不关心的本地更改,我决定创建一个新的克隆(以前我使用 GUI 工具,但它们是如此混乱和限制,以至于我放弃了它并潜入 git命令 ;).
我做到了:
cd /D/Projects/OpenSource/VisualFSharp2
git init
git clone https://github.com/abelbraaksma/visualfsharp
git fetch https://github.com/Microsoft/visualfsharp
git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
git fetch upstream
git checkout master
git merge upstream/master
最后两个命令给出:
git checkout master
Already on 'master'
Your branch is up to date with 'upstream/master'.
git merge upstream/master
Already up to date.
我意识到我做错了一些事情,因为我来自 SVN 和 Mercurial 世界,所以我经常被术语搞糊涂。
我知道目前我在上游仓库的 "master" 中。但我需要从上游回购合并到原点(我的叉子)回购。我假设我需要将本地副本更新为我的叉子的任何头部(但 git checkout master
不这样做)。
我基本上是尝试遵循this guide on syncing, combined with configuring remote points。
我在哪里感到困惑或更好,我落后了哪些命令?
做 git remote -v
给我:
origin https://github.com/abelbraaksma/visualfsharp (fetch)
origin https://github.com/abelbraaksma/visualfsharp (push)
upstream https://github.com/Microsoft/visualfsharp (fetch)
upstream https://github.com/Microsoft/visualfsharp (push)
TL;DR
你没问题,但你有一个额外的存储库,你可能应该删除它。您通常应该首先克隆(使用 git clone
)要让 Git 调用 origin
的存储库,然后 git remote add upstream <the other url>
并从那里开始工作。
阅读下面的详细说明,了解您现在拥有的内容以及如何使用它。
长:你做了什么,详细
git init
这会在当前目录中创建一个新的空 Git 存储库。 (如果这里已经有一个 Git 存储库——如果 git rev-parse --git-dir
会打印一些目录名称,而不是失败并显示 "I find no repository"——它基本上什么都不做,可以安全地 运行。这里有一些极端情况,但你不太可能 运行 进入它们。)既然你打算克隆一个存储库,你真的不想这样做,因为 git clone
也做一个git init
,我们稍后会看到。
在我们继续下面的 git clone
之前,让我们花点时间记下一个新的空存储库的奇怪状态。您现在可能熟悉 分支名称 像 master
实际上只是保存一 (1) 次提交的哈希 ID 的想法。 Git 使用名称查找分支上的 last 提交,Git 调用 tip 提交。 Git 然后使用 tip commit 找到以前的或 parent commit,并使用 parent 的 parent 来回溯历史。通过遵循父链,Git 从分支名称中找到所有 可达 的提交。
但是空存储库没有提交。 master
的名称 master
没有指向的提示——在 master
中没有最新的提交,其哈希 ID 可以存储在名称 master
下。 Git 的解决方案是 没有 master
分支。同时,Git 声明您是 "on branch master",正如 git status
会说的那样——所以您 在一个尚不存在的分支上 .
这个奇怪的因素在后面。现在,让我们继续 git clone
,看看它做了什么。在这种情况下,它会创建另一个单独的存储库,您随后根本不会使用它。
git clone https://github.com/abelbraaksma/visualfsharp
这主要相当于一系列命令:
mkdir visualfsharp
: 在当前目录下新建子目录(当前为/D/Projects/OpenSource/VisualFSharp2
)
cd visualfsharp
:进入新的子目录
git remote add origin https://github.com/abelbraaksma/visualfsharp
:添加名为 origin
的遥控器(这也为其配置了一些设置)
git fetch origin
: 获取他们所有的提交
git checkout <em>somebranch</em>
,其中 somebranch
是通常 master
:从 origin/*
名称之一创建一个本地分支名称并使其成为当前分支。
完成这些后,您将返回到原始目录(即,仍然是 /D/Projects/OpenSource/VisualFSharp2
)。请注意,您的原始目录是一个 Git 存储库,其 visualfsharp
子目录是另一个。
我们将看到您现在再次执行这些命令中的大部分,但这一次,应用于您当前为空的存储库,它处于您在 master
但 master
不存在。
git fetch https://github.com/Microsoft/visualfsharp
这会在 https://github.com/Microsoft/visualfsharp
调用 Git 并从中获取提交和其他对象,并将其放入您之前空的存储库(不是您刚刚创建的克隆!)。就像 git fetch <em>remote</em>
除了没有远程跟踪名称——没有 origin/*
或 upstream/*
—因为没有远程可用于构造此类名称。 git fetch
的这种特殊形式可以追溯到古代(2005 年),在 git remote
发明之前,人们可能永远不应该使用它。这不是有害,只是在这里也没有帮助。
git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
这些很好:他们设置了两个 遥控器。遥控器只是一个简称:
- 保存一个URL,
- 提供远程跟踪名称的前导部分,分别为
upstream/*
和origin/*
。
git fetch upstream
这 几乎 是您之前 git fetch
的重复。不过这一次,您的 Git 使用您指定的名称 — upstream
— 来获得 URL。所以你的 Git 再次调用 https://github.com/Microsoft/visualfsharp
的 Git。自上次获取以来,您的 Git 从他们那里获得了任何新的提交(以及任何其他必要的 Git 对象以配合这些提交)——可能 none,具体取决于您在第一个和第二个。如果您没有 运行 之前的 git fetch
,这将在获取所有提交时获取每个 Git 对象。
但是现在,在获得提交后,有一个关键的区别:你的 Git 使用 他们所有的分支名称 并将它们重命名为你拼写的远程跟踪名称上游/<em>随便</em>
。它现在可以执行此操作,因为现在您使用的是遥控器,而不仅仅是原始 URL。远程 - 文字字符串 upstream
- 让你重命名。1 所以你的 Git 和他们的 Git 非常快速地传输所有新对象(可能 none),然后你的 Git 根据他们的 master
等等设置你的 upstream/master
等等。
git checkout master
这就是存储库奇怪状态的来源。您的 Git 会说:
Branch master set up to track remote branch master from upstream.
Already on 'master'
发生的事情是git checkout
找master
而没有找到(因为你没有分支),所以创造了一个。首先,它查看了您所有的远程跟踪名称,在本例中为 upstream/*
。它找到了一个匹配的:master
vs upstream/master
。所以它创建了你的 master
,指向与你的 upstream/master
相同的提交。然后它还会将您的 master
设置为 upstream/master
作为其 upstream 设置。
完成所有操作后——创建你的 master
——git checkout
试图将你放到你的 master
上,结果发现你只在你的 master
上并打印令人困惑的 "already on" 消息。不过,它在此过程中正确附加了您的 HEAD,检查了所有文件,即将它们复制到索引和工作树中。
您可能希望也可能不希望您的 master
以这种方式设置——您更有可能希望您的 master
开始指向与您的 origin/master
相同的提交,一旦你创建了一个 origin/master
,并将 origin/master
设置为它的上游。有关什么是上游的更多信息——即,将一个分支设置为 track2 另一个分支意味着什么——参见,例如, to .
您在此处的最后一条命令是:
git merge upstream/master
你自己的 master
刚刚从你的 upstream/master
创建,所以没有什么可以合并:两个名字都指向同一个提交哈希编号.
您尚未从 origin
中获取任何内容。您现在可能应该这样做:
git fetch origin
一旦你这样做,你将拥有 origin/master
以及 upstream/master
。3 如果你希望,正如我怀疑的那样,拥有你自己的 master
跟踪 origin/master
而不是 upstream/master
(并从那里开始),你应该:
- 确保没有什么要提交的(不应该给出上面的顺序,但在使用之前检查总是明智的
git reset --hard
);
- 运行
git reset --hard origin/master
使您的 master
指向与 origin/master
相同的提交;和
- 运行
git branch --set-upstream-to=origin/master master
更改上游设置。
现在你可以运行git merge upstream/master
。如果在您自己的分叉发生后上游有新的提交,这将合并这些提交,如果需要则使用完全合并,或者如果可能的话使用快进非真正合并操作。
在任何情况下,您可能都想删除额外的存储库。
1Git 实现重命名的底层机制非常复杂,可能是出于历史原因,但在正常实践中它只是 "change their master
to your <em>remote</em>/master
" 和依此类推
2请注意 Git 在这里使用了更令人困惑的术语:如果分支名称 tracks a remote-tracking name(这是你的 Git 根据在另一个 Git 中找到的名称创建的本地名称,另一个 URL 是通过 remote) 然后我们称该分支(或分支名称)为 upstream。这与跟踪文件和未跟踪文件完全不同。哎呀!
3我在这里假设 https://github.com/abelbraaksma/visualfsharp
的 Git 存储库是您自己的,并且您使用 GitHub 的存储库创建了它"fork a repository" Web GUI 界面中的可点击按钮。当您这样做时,GitHub 在 GitHub 本身上做了一些复杂的 git clone
,从您选择的任何源存储库在那里创建您的存储库。这意味着您的 GitHub 存储库具有与原始源存储库相同的所有分支。
(克隆 GitHub 不会重命名分支。它还具有特殊的 GitHub-only 功能设置以允许 GitHub 提供的拉取请求工具;这不是 Git 的一部分。GitHub 人员还安排在幕后共享底层磁盘对象,并使用各种其他技巧使它比它更快做得很天真。所以它是一个常规的克隆 原则上 ,但他们已经对其进行了调整,使其通过 Web 界面更有用。这就是他们让你使用 GitHub 的方式而不是自己全部完成。)
我做的事情和你做的很相似,我是这样做的:
- 获取叉子的 url。
- 切换到终端。
cd
到我们要克隆的目录。
git clone fork-url-here
将克隆我们的分支并将其设置为 remote/origin
.
cd fork-name/
切换到克隆的目录。
git remote add upstream upstream-url-here
将上游设置为 remote/upstream
.
git fetch upstream
从上游获取 所有分支 。
git checkout master
因为我们已经在 origin/master 上,所以我们收到一条消息通知我们同样的情况。所以,一切都很好,这 不是 表示有问题。
git branch -a
列出所有本地 + remote/origin/*
+ remote/upstream/*
分支。其中之一是 upstream/master
(最初我使用 git branch
,它只显示本地分支机构,这让我有点困惑,因为我在列表中看不到 upstream/master
)。
git merge upstream/master
这会将 upstream/master
分支合并到您当前的分支,即 origin/master
,从而同步到上游。
出现您遇到的问题是因为就在您将上游添加为远程之前,您从中获取(代码块中的第四行)。这将阻止您从上游获取所有分支。其他的我觉得还好。
P.S.: 我可以看出这是一个老问题,但我只是想我可能会帮助 git 初学者(像我一样),他们可能会匆忙而无法阅读torek 给出了非常好的和信息丰富的答案。
Edit/Extension 1:另一件事是强制fork的(origin)master与原始repo的(upstream)master处于同一级别。
!!!注意:这将丢弃对您的 origin master 所做的任何和所有提交!!!
如果您完全确定要执行此操作,请将上述步骤中的步骤 9 替换为以下内容:
git reset --hard upstream/master
将用 upstream/master. 的内容替换 origin/master 的内容(当然是在本地)
git push origin master --force
将强制推送您所做的更改到远程源。
我建议进行此更改,因为我最近不得不自己做这件事,并且发现这可以帮助某人(前提是他们知道自己在做什么)。但是,由于它也有可能破坏有价值的工作,所以我一再强调其中的风险。
我想我已经通读了一些教程,但我仍然停留在一些完全基础的东西上(我几乎从不使用命令行 git,所以请耐心等待 ;))。
我只想从上游仓库更新我的叉子 (https://github.com/abelbraaksma/visualfsharp) to the latest version of Master (https://github.com/Microsoft/visualfsharp)。由于我有一些我不关心的本地更改,我决定创建一个新的克隆(以前我使用 GUI 工具,但它们是如此混乱和限制,以至于我放弃了它并潜入 git命令 ;).
我做到了:
cd /D/Projects/OpenSource/VisualFSharp2
git init
git clone https://github.com/abelbraaksma/visualfsharp
git fetch https://github.com/Microsoft/visualfsharp
git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
git fetch upstream
git checkout master
git merge upstream/master
最后两个命令给出:
git checkout master
Already on 'master'
Your branch is up to date with 'upstream/master'.
git merge upstream/master
Already up to date.
我意识到我做错了一些事情,因为我来自 SVN 和 Mercurial 世界,所以我经常被术语搞糊涂。
我知道目前我在上游仓库的 "master" 中。但我需要从上游回购合并到原点(我的叉子)回购。我假设我需要将本地副本更新为我的叉子的任何头部(但 git checkout master
不这样做)。
我基本上是尝试遵循this guide on syncing, combined with configuring remote points。
我在哪里感到困惑或更好,我落后了哪些命令?
做 git remote -v
给我:
origin https://github.com/abelbraaksma/visualfsharp (fetch) origin https://github.com/abelbraaksma/visualfsharp (push) upstream https://github.com/Microsoft/visualfsharp (fetch) upstream https://github.com/Microsoft/visualfsharp (push)
TL;DR
你没问题,但你有一个额外的存储库,你可能应该删除它。您通常应该首先克隆(使用 git clone
)要让 Git 调用 origin
的存储库,然后 git remote add upstream <the other url>
并从那里开始工作。
阅读下面的详细说明,了解您现在拥有的内容以及如何使用它。
长:你做了什么,详细
git init
这会在当前目录中创建一个新的空 Git 存储库。 (如果这里已经有一个 Git 存储库——如果 git rev-parse --git-dir
会打印一些目录名称,而不是失败并显示 "I find no repository"——它基本上什么都不做,可以安全地 运行。这里有一些极端情况,但你不太可能 运行 进入它们。)既然你打算克隆一个存储库,你真的不想这样做,因为 git clone
也做一个git init
,我们稍后会看到。
在我们继续下面的 git clone
之前,让我们花点时间记下一个新的空存储库的奇怪状态。您现在可能熟悉 分支名称 像 master
实际上只是保存一 (1) 次提交的哈希 ID 的想法。 Git 使用名称查找分支上的 last 提交,Git 调用 tip 提交。 Git 然后使用 tip commit 找到以前的或 parent commit,并使用 parent 的 parent 来回溯历史。通过遵循父链,Git 从分支名称中找到所有 可达 的提交。
但是空存储库没有提交。 master
的名称 master
没有指向的提示——在 master
中没有最新的提交,其哈希 ID 可以存储在名称 master
下。 Git 的解决方案是 没有 master
分支。同时,Git 声明您是 "on branch master",正如 git status
会说的那样——所以您 在一个尚不存在的分支上 .
这个奇怪的因素在后面。现在,让我们继续 git clone
,看看它做了什么。在这种情况下,它会创建另一个单独的存储库,您随后根本不会使用它。
git clone https://github.com/abelbraaksma/visualfsharp
这主要相当于一系列命令:
mkdir visualfsharp
: 在当前目录下新建子目录(当前为/D/Projects/OpenSource/VisualFSharp2
)cd visualfsharp
:进入新的子目录git remote add origin https://github.com/abelbraaksma/visualfsharp
:添加名为origin
的遥控器(这也为其配置了一些设置)git fetch origin
: 获取他们所有的提交git checkout <em>somebranch</em>
,其中somebranch
是通常master
:从origin/*
名称之一创建一个本地分支名称并使其成为当前分支。
完成这些后,您将返回到原始目录(即,仍然是 /D/Projects/OpenSource/VisualFSharp2
)。请注意,您的原始目录是一个 Git 存储库,其 visualfsharp
子目录是另一个。
我们将看到您现在再次执行这些命令中的大部分,但这一次,应用于您当前为空的存储库,它处于您在 master
但 master
不存在。
git fetch https://github.com/Microsoft/visualfsharp
这会在 https://github.com/Microsoft/visualfsharp
调用 Git 并从中获取提交和其他对象,并将其放入您之前空的存储库(不是您刚刚创建的克隆!)。就像 git fetch <em>remote</em>
除了没有远程跟踪名称——没有 origin/*
或 upstream/*
—因为没有远程可用于构造此类名称。 git fetch
的这种特殊形式可以追溯到古代(2005 年),在 git remote
发明之前,人们可能永远不应该使用它。这不是有害,只是在这里也没有帮助。
git remote add upstream https://github.com/Microsoft/visualfsharp git remote add origin https://github.com/abelbraaksma/visualfsharp
这些很好:他们设置了两个 遥控器。遥控器只是一个简称:
- 保存一个URL,
- 提供远程跟踪名称的前导部分,分别为
upstream/*
和origin/*
。
git fetch upstream
这 几乎 是您之前 git fetch
的重复。不过这一次,您的 Git 使用您指定的名称 — upstream
— 来获得 URL。所以你的 Git 再次调用 https://github.com/Microsoft/visualfsharp
的 Git。自上次获取以来,您的 Git 从他们那里获得了任何新的提交(以及任何其他必要的 Git 对象以配合这些提交)——可能 none,具体取决于您在第一个和第二个。如果您没有 运行 之前的 git fetch
,这将在获取所有提交时获取每个 Git 对象。
但是现在,在获得提交后,有一个关键的区别:你的 Git 使用 他们所有的分支名称 并将它们重命名为你拼写的远程跟踪名称上游/<em>随便</em>
。它现在可以执行此操作,因为现在您使用的是遥控器,而不仅仅是原始 URL。远程 - 文字字符串 upstream
- 让你重命名。1 所以你的 Git 和他们的 Git 非常快速地传输所有新对象(可能 none),然后你的 Git 根据他们的 master
等等设置你的 upstream/master
等等。
git checkout master
这就是存储库奇怪状态的来源。您的 Git 会说:
Branch master set up to track remote branch master from upstream.
Already on 'master'
发生的事情是git checkout
找master
而没有找到(因为你没有分支),所以创造了一个。首先,它查看了您所有的远程跟踪名称,在本例中为 upstream/*
。它找到了一个匹配的:master
vs upstream/master
。所以它创建了你的 master
,指向与你的 upstream/master
相同的提交。然后它还会将您的 master
设置为 upstream/master
作为其 upstream 设置。
完成所有操作后——创建你的 master
——git checkout
试图将你放到你的 master
上,结果发现你只在你的 master
上并打印令人困惑的 "already on" 消息。不过,它在此过程中正确附加了您的 HEAD,检查了所有文件,即将它们复制到索引和工作树中。
您可能希望也可能不希望您的 master
以这种方式设置——您更有可能希望您的 master
开始指向与您的 origin/master
相同的提交,一旦你创建了一个 origin/master
,并将 origin/master
设置为它的上游。有关什么是上游的更多信息——即,将一个分支设置为 track2 另一个分支意味着什么——参见,例如,
您在此处的最后一条命令是:
git merge upstream/master
你自己的 master
刚刚从你的 upstream/master
创建,所以没有什么可以合并:两个名字都指向同一个提交哈希编号.
您尚未从 origin
中获取任何内容。您现在可能应该这样做:
git fetch origin
一旦你这样做,你将拥有 origin/master
以及 upstream/master
。3 如果你希望,正如我怀疑的那样,拥有你自己的 master
跟踪 origin/master
而不是 upstream/master
(并从那里开始),你应该:
- 确保没有什么要提交的(不应该给出上面的顺序,但在使用之前检查总是明智的
git reset --hard
); - 运行
git reset --hard origin/master
使您的master
指向与origin/master
相同的提交;和 - 运行
git branch --set-upstream-to=origin/master master
更改上游设置。
现在你可以运行git merge upstream/master
。如果在您自己的分叉发生后上游有新的提交,这将合并这些提交,如果需要则使用完全合并,或者如果可能的话使用快进非真正合并操作。
在任何情况下,您可能都想删除额外的存储库。
1Git 实现重命名的底层机制非常复杂,可能是出于历史原因,但在正常实践中它只是 "change their master
to your <em>remote</em>/master
" 和依此类推
2请注意 Git 在这里使用了更令人困惑的术语:如果分支名称 tracks a remote-tracking name(这是你的 Git 根据在另一个 Git 中找到的名称创建的本地名称,另一个 URL 是通过 remote) 然后我们称该分支(或分支名称)为 upstream。这与跟踪文件和未跟踪文件完全不同。哎呀!
3我在这里假设 https://github.com/abelbraaksma/visualfsharp
的 Git 存储库是您自己的,并且您使用 GitHub 的存储库创建了它"fork a repository" Web GUI 界面中的可点击按钮。当您这样做时,GitHub 在 GitHub 本身上做了一些复杂的 git clone
,从您选择的任何源存储库在那里创建您的存储库。这意味着您的 GitHub 存储库具有与原始源存储库相同的所有分支。
(克隆 GitHub 不会重命名分支。它还具有特殊的 GitHub-only 功能设置以允许 GitHub 提供的拉取请求工具;这不是 Git 的一部分。GitHub 人员还安排在幕后共享底层磁盘对象,并使用各种其他技巧使它比它更快做得很天真。所以它是一个常规的克隆 原则上 ,但他们已经对其进行了调整,使其通过 Web 界面更有用。这就是他们让你使用 GitHub 的方式而不是自己全部完成。)
我做的事情和你做的很相似,我是这样做的:
- 获取叉子的 url。
- 切换到终端。
cd
到我们要克隆的目录。 git clone fork-url-here
将克隆我们的分支并将其设置为remote/origin
.cd fork-name/
切换到克隆的目录。git remote add upstream upstream-url-here
将上游设置为remote/upstream
.git fetch upstream
从上游获取 所有分支 。git checkout master
因为我们已经在 origin/master 上,所以我们收到一条消息通知我们同样的情况。所以,一切都很好,这 不是 表示有问题。git branch -a
列出所有本地 +remote/origin/*
+remote/upstream/*
分支。其中之一是upstream/master
(最初我使用git branch
,它只显示本地分支机构,这让我有点困惑,因为我在列表中看不到upstream/master
)。git merge upstream/master
这会将upstream/master
分支合并到您当前的分支,即origin/master
,从而同步到上游。
出现您遇到的问题是因为就在您将上游添加为远程之前,您从中获取(代码块中的第四行)。这将阻止您从上游获取所有分支。其他的我觉得还好。
P.S.: 我可以看出这是一个老问题,但我只是想我可能会帮助 git 初学者(像我一样),他们可能会匆忙而无法阅读torek 给出了非常好的和信息丰富的答案。
Edit/Extension 1:另一件事是强制fork的(origin)master与原始repo的(upstream)master处于同一级别。
!!!注意:这将丢弃对您的 origin master 所做的任何和所有提交!!!
如果您完全确定要执行此操作,请将上述步骤中的步骤 9 替换为以下内容:
git reset --hard upstream/master
将用 upstream/master. 的内容替换 origin/master 的内容(当然是在本地)
git push origin master --force
将强制推送您所做的更改到远程源。
我建议进行此更改,因为我最近不得不自己做这件事,并且发现这可以帮助某人(前提是他们知道自己在做什么)。但是,由于它也有可能破坏有价值的工作,所以我一再强调其中的风险。