Git: Fork / Remote / Clone 的概念

4

我试图理解/可视化与forking a repo相关的元素。 我的起始参考是这个帮助页面

第一个问题

当我在GitHub上fork了一个repo,例如Spoon-Knife(即在其网站上单击Fork按钮),这是否意味着Spoon-Knife被复制到我的GitHub账户中? 是否真的发生了实际的复制,还是只是一个概念?

第二个问题

帮助页面中的下一步是进行clone

$ git clone git@github.com:username/Spoon-Knife.git

该命令在我的本地机器上复制了源代码。 它是从我在GitHub帐户中分叉/复制的repo克隆的(请参见我的第一个问题)? 还是从原始的Spoon-Knife repo克隆的?

第三个问题

关于配置远程的步骤:

当克隆一个repo时,它有一个名为origin的默认远程,指向您在GitHub上的fork而不是它被fork的原始repo。 要跟踪原始repo,您需要添加另一个名为upstream的远程。

因此,origin是我们本地副本和我在GitHub帐户上的repo副本之间的某种“代理”吗? upstream呢?

提前感谢您的帮助。

6个回答

4
  1. 当你“fork”代码库时,实际上是在他们的git仓库上创建了一个分支,然后你可以把本地代码提交到这个分支上。

  2. 你本地克隆的代码只是从你在git-hub上创建的分支克隆下来,并链接到它。记住,分支只是指向提交对象的指针,所以当你“fork”时,只是在他们的主分支上添加了一个分支名称,用于指向当前的最新提交。

  3. 在git中,“远程仓库”只是外部地址上存储的仓库的名称。你默认的“origin”是由git设置的,只是一个命名的远程仓库。“upstream”只是另一个名称,指向最初分支出的原始主分支,这样你就可以在主分支和自己的分支之间拉取变更。你可以使用git remote -v查看你的远程仓库,并轻松添加任何外部可用git仓库上的任何分支。


#1和#2的解释非常出色。谢谢!那么,在我fork之后,origin会自动创建吗? - moey
当我从原始/主分支拉取新的更改时,我是将它们拉到origin还是直接拉到我的本地副本? - moey
1
当你克隆时,origin 会被创建。远程仓库仅仅是一个名称和指针,例如如果你尝试以下命令:git init --bare Base; git clone Base dev1; cd dev1; git remote,你会得到 origin 作为名称,并且路径指向 dev1 指向的 Base 仓库,在 git-hub 上是一个 ssh 引用,在我的示例中是一个简单的路径,但两者都只是告诉 git 从哪里获取信息。远程仓库只是跟踪其他人的代码库,而 origin 只是使用 git clone 时 git 使用的默认名称。 - Mark Fisher
针对您在评论中的第二个问题,关于“将它们拉到原点”,不,您应该将它们拉取到您的本地分支。正如我所说,将远程视为指向别人存储库的指针,它有一个名称(例如,“origin”)和一个值(例如路径或ssh引用,或git: 引用等) - Mark Fisher

4
你需要区分 forkclone 的概念。
  • clone 是 Git 的概念,GitHub 出现之前就存在:当你克隆一个仓库时,你将所有的历史和数据复制到自己新建的仓库中。此外,在新仓库中还会自动创建一个名为 originremote,它指向你克隆的仓库。

  • fork 是 GitHub 的概念,核心 Git 并不知道。当你 fork 一个 GitHub 项目时,你会创建一个与原始项目完全相同的 GitHub 项目,并自动更新所有 GitHub 特性例如 fork 图。在幕后,fork 还包括克隆原始项目中的 Git 仓库并在你新创建的项目中创建一个新的 Git 仓库。

当你想从自己的私有设备上工作于一个 GitHub 项目时,你需要首先克隆该仓库,无论它是你自己的还是别人的。如果你从 你自己的 GitHub 项目克隆,你会得到它的 origin,但如果你也想要原始项目作为远程仓库,你需要手动添加它(例如,取名为 upstream)。


谢谢,@Daniel!为了澄清你最后一段的意思:如果我从我的GitHub项目克隆,origin指向我的GitHub存储库,对吗?听起来像是_remote_是一个本地指针,指向远程存储库。 - moey
当原始项目有新更改时,我需要先在GitHub上更新我的项目,然后再更新本地副本吗?或者,我可以直接从原始项目更新到我的计算机吗? - moey
1
@Siku-Siku.Com 正确,remote 是指向另一个存储库的本地指针。至于您的第二个问题,您有两个选项:要更新您的 GitHub 项目,请在 GitHub 中使用“快进”按钮(仅当您尚未提交任何项目时才可能)。要更新您机器上的存储库,请将原始项目的存储库添加为远程 (upstream 上方),然后从中拉取。然后,如果需要,您也可以将其推送到您的 GitHub 项目。 - Daniel Hershcovich

2

第一个问题:

你复制了它。实际上这是一种克隆。现在你在你的github账户中拥有该项目的副本(实际上是其中一个分支的副本)。

第二个问题:

git clone命令会克隆你提供的存储库。 因此,$ git clone git@github.com:username/Spoon-Knife.git会从username存储库克隆Spoon-Knife。如果这是你自己的账户,那么这就是Spoon-Knife存储库的副本 :)

第三个问题:

origin不是代理,它只是另一个存储库的名称。 例如,以下命令将添加一个名为local_srv的存储库:

git remote add local_srv /path/to/local/srv

upstream只是另一个远程仓库。您可以配置它来从中拉取更新(获取更新)。

在您的情况下,origin是您的GitHub仓库(我把这个远程仓库称为github),您可以将upstream远程仓库添加到原始的Spoon-Knife代码库中。因此,您可以在本地工作,将更改推送到您的GitHub账户(例如:git push origin master),然后使用git pull upstream master获取Spoon-Knife项目的新更新。

注意:这里我只使用了master分支,但您可以用您喜欢的分支替换它。


谢谢,@Geoffroy!当我第一次fork这个项目时,origin是自动创建的吗?还是它是从克隆命令中产生的副产品? - moey
是的,您可以使用 git remote 命令查看当前远程仓库列表 :) - Geoffroy

1

3个仓库

original - {GitHub}/octocat/Spoon-Knife  
forked   - {GitHub}/   mine/Spoon-Knife  
local    -  {local}        /Spoon-Knife
  1. 当你“fork”时,实际上你有一个副本,因为你可以读写它。然而,最好将其视为一种有效地“在原始git存储库上创建分支并对其进行编写”的方式。

  2. “fork”操作将original复制到您的GitHub帐户中。您可以直接从local克隆推送到forked(而不是original)。

  3. 简单来说,remote是指外部地址上存储库的名称。
    “origin”-指向forked(“origin”是默认的remote名称)
    “upstream”-指向original,以便您可以获取对您的存储库所做更改的更新

您可以使用git remote -v查看您的远程,并轻松添加它们以跟踪任何外部可用的git存储库上的任何分支。

部分源自Mark的答案。


1
当我在GitHub上fork一个repo,例如Spoon-Knife,这是否意味着Spoon-Knife被复制到了我的GitHub账户中?
是的。
实际上发生了真正的复制还是只是一个概念?
这是Github端的实现细节。对你来说不重要。(我非常确定他们共享存储)。
它是从我在GitHub账户中forked / copied repo克隆的吗?还是从原始的Spoon-Knife repo克隆的?
由于您将其指向了用户帐户的repo,因此它将从那里复制。此时两个fork的内容是相同的。
那么,origin是我们本地副本和我在GitHub账户上的repo副本之间的某种“代理”吗?upstream又如何?
不完全是。 "origin" 只是 GitHub 上存储库的标识符,使您更容易与其通信。 "upstream" 也可以起到同样的作用。您不需要设置这些远程仓库,但对于您经常使用(推送或拉取更改)的所有存储库都拥有它们会使事情变得更加容易。名称 "origin" 和 "upstream" 也只是约定俗成的(您应该遵循),没有任何 "魔法"。

谢谢,Thilo。关于你最后的回答,我们能否将其指向原始仓库?如果是的话,那么似乎我们不需要进行 fork。 - moey
1
只有在想要进行更改时才需要 fork。 你不需要在 Github 上拥有这个 fork(可以仅在本地或其他服务上拥有),但是 Github 非常方便,特别是因为你可以使用所有漂亮的网页和社交功能来推送和审查变更集。 - Thilo
1
啊...现在更清楚了:只有当我需要进行更改时才进行分叉。我认为因为很多人/网站都说“在GitHub上对我进行分叉”,让我盲目地去分叉,尽管有时我只想获取源代码。(: - moey
等一下...那么,我们可以直接从原始仓库克隆吗? - moey
1
是的,您可以直接克隆您在Github或其他地方具有读取访问权限的任何存储库。要获取GitHub存储库源代码的本地副本,您可以将其克隆。 - Thilo

1

使用 Git,每个存储库都有完整的历史记录。实际上(除了在本地存储库之间共享数据的一些优化之外),每个存储库都是另一个存储库的克隆。或者用 Git Hub 的说法,就是 fork(它们是同一件事)。

因此,您有三个存储库:原始开发人员存储库、Git Hub 上的克隆(他们称其为 fork)以及此克隆的本地克隆。名称“origin”只是一个简写名称,用于引用 Git Hub 上的存储库(您的第一个克隆)。如果没有这个简写,您将不得不在每个步骤中提供存储库的完整 URI。

存储库可以有许多这样的简写名称,指向其他存储库。建议它们都是同一个原始存储库的克隆,以便历史记录成为具有单个根的简单有向无环图。

您可以在没有 Git Hub 中间克隆的情况下工作,但由于您没有对原始开发人员存储库的写访问权限,并且使您的私有存储库可访问可能是不切实际的,因此可以使用 Git Hub 上的此存储库作为您和原始作者之间的补丁通信网关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接