我认为我已经阅读了一些教程,并且坚持使用完全基础的东西(我几乎从不使用命令行git,所以请耐心;))。
我要做的就是从上游存储库中将fork(https://github.com/abelbraaksma/visualfsharp)更新为最新版本的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
已经在“主人”上
您的分支机构的最新信息是“上游/母版”。
git merge upstream/master
已经是最新的。
我意识到我做错了一些事情,并且由于我来自SVN和Mercurial世界,所以我经常对术语感到困惑。
我知道目前我是上游仓库的“主管”。但是我需要将上游回购合并到原始(我的fork)回购中。我假设我需要将本地副本更新为我的叉子的头部(但是git checkout master
不会这样做)。
我基本上是尝试将this guide on syncing与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)
答案 0 :(得分:2)
您还可以,但是您还有一个额外的存储库,您可能应该删除它。通常,您应该首先克隆(使用git clone
),让您的Git调用origin
,然后git remote add upstream <the other url>
并从那里开始工作。
阅读下面的详细说明,以了解您现在拥有的内容以及如何使用它。
git init
这将在当前目录中创建一个新的空Git存储库。 (如果这里已经有一个Git储存库-如果git rev-parse --git-dir
会打印一些目录名,而不是失败并说“我找不到储存库”,则它基本上什么也不做,因此可以安全运行。由于您打算克隆存储库,因此您实际上并不想这样做,因为git clone
也会执行{{1} },我们稍后会看到。
在继续下面的git init
之前,让我们花点时间记录一下新的空存储库的怪异状态。您现在可能已经熟悉这样的想法,即像git clone
这样的分支名称实际上仅持有一(1)个提交的哈希ID。 Git使用该名称在分支上找到 last 提交,Git将其称为 tip commit 。然后,Git使用技巧提交来查找先前的提交或 parent 提交,并使用父级的父级回顾历史。通过跟踪父链,Git从分支名称中找到所有可达的提交。
但是空的存储库没有提交。名称master
不能指向master
指向-master
中没有最新提交,其哈希ID可以存储在名称master
下。 Git的解决方案是还没有一个master
分支。同时,如master
所说,Git声明您在“分支主服务器上” —因此,您在尚不存在的分支上。
此怪异因素会在以后出现。现在,让我们继续进行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 somebranch
通常为somebranch
:从master
名称之一创建本地分支名称,并使其成为当前分支。完成这些操作后,您将返回到原始目录(即,仍为origin/*
)。请注意,您的原始目录是一个Git存储库,而其/D/Projects/OpenSource/VisualFSharp2
子目录是另一个。
我们现在将看到您再次执行这些命令中的大多数命令,但是这次将其应用于您当前为空的存储库,该存储库处于您处于visualfsharp
但{{1 }}不存在。
master
这将调用master
处的Git,并从它们中获取提交和其他对象,并将其提交到以前为空的存储库中(而不是刚刚创建的克隆!)。就像git fetch https://github.com/Microsoft/visualfsharp
一样,除了没有远程跟踪名称(没有https://github.com/Microsoft/visualfsharp
或git fetch remote
)之外,因为没有远程可用于构造这样的名称。 origin/*
的这种特殊形式可以追溯到upstream/*
发明之前的远古时代(2005年),也许永远不要使用它。这不是有害,在这里也不是有用。
git fetch
这些很好:他们设置了两个远程。遥控器只是一个简称:
git remote
和git remote add upstream https://github.com/Microsoft/visualfsharp
git remote add origin https://github.com/abelbraaksma/visualfsharp
。upstream/*
这几乎是您先前的origin/*
的重复。但是,这次,您的Git使用您分配的名称git fetch upstream
来获取URL。因此,您的Git再次调用git fetch
上的Git。自上次获取以来,您的Git从它们获取任何新提交(以及与这些提交一起进行的任何其他必要的Git对象)-可能没有,这取决于您在第一次获取和第二次获取之间相隔了多长时间。如果您没有运行早期的upstream
,则将在获取所有提交的同时获取每个Git对象。
但是现在,有了提交之后,就存在一个关键的区别:您的Git会使用所有分支名称,并将其重命名为拼写为https://github.com/Microsoft/visualfsharp
的远程跟踪名称。它现在可以执行此操作,因为现在您使用的是远程URL,而不仅仅是原始URL。遥控器-文字字符串git fetch
-为您重命名。 1 因此,您的Git及其Git可以非常快速地传输所有新对象(可能没有),然后Git进行设置您的upstream/whatever
等,基于他们的upstream
等。
upstream/master
这是存储库的怪异状态出现的地方。您的Git会说:
master
发生了什么事,git checkout master
寻找了Branch master set up to track remote branch master from upstream.
Already on 'master'
,并且找不到它(因为您没有分支),所以它创建了一个。首先,它会查看您所有的远程跟踪名称,在这种情况下为git checkout
。它找到了一个匹配的:master
与upstream/*
。因此,它创建了您的master
,并指向与您的upstream/master
相同的提交。然后,它还将您的master
设置为upstream/master
作为其上游设置。
完成所有操作后-创建master
-upstream/master
试图将您放到master
上,发现您只是在git checkout
上并打印出令人困惑的内容“已经开始”消息。尽管如此,它还是在过程中正确地连接了HEAD,签出了所有文件,即将它们复制到索引和工作树中。
您可能希望或不希望您的master
设置为这种方式-一旦您完成操作,您就更可能希望master
指向与master
相同的提交创建master
,并将origin/master
设置为其上游。有关上游是什么的更多信息,即,将一个分支设置为 track 2 意味着另一个分支,请参见my answer到{{ 3}}。
您在这里的最后一条命令是:
origin/master
您的origin/master
刚从您的git merge upstream/master
中创建,因此没有任何可合并的地方:这两个名称都指向相同的提交哈希ID。
您尚未从master
获取任何信息。您现在可能应该这样做:
upstream/master
完成后,您将同时拥有origin
和git fetch origin
。 3 如我所愿,如果您希望拥有自己的origin/master
音轨upstream/master
而非master
(并从那里开始),您应该:
origin/master
之前检查总是明智的做法); upstream/master
,使您的git reset --hard
指向与git reset --hard origin/master
相同的提交;和master
更改上游设置。 现在,您可以运行origin/master
。如果上游在您进行了自己的分叉之后有了新的提交,则将合并这些提交,如果需要,可以使用完全合并,或者如果可能的话,使用快进非真正合并操作。
无论如何,您可能想要删除额外的存储库。
1 Git实现此重命名的基本机制非常复杂,可能是出于历史原因,但在正常实践中,它只是“将其git branch --set-upstream-to=origin/master master
更改为您的git merge upstream/master
等等。
2 请注意,Git在这里使用了更加混乱的术语:如果分支名称 tracks 是远程跟踪名称(这是本地您的Git创建的名称基于在另一个Git中找到的名称,该名称的URL是通过 remote 找到的,然后我们将该分支称为(或分支名称)为上游。这与跟踪文件和未跟踪文件完全不同。 kes!
3 我在这里假设master
上的Git存储库是您自己的,并且您是使用其Web GUI界面中GitHub的“ fork存储库” clicky按钮创建的。当您这样做时,GitHub在GitHub本身上做了一个稍微复杂的remote/master
,可以从您选择的任何源存储库中创建存储库。这意味着您的GitHub存储库具有与原始源存储库相同的所有分支。
(克隆的GitHub不会重命名分支。它还具有特殊的仅限GitHub的功能,以允许GitHub提供的拉取请求工具;这不是Git的一部分。GitHub伙计们还安排共享以下内容:将磁盘对象隐藏在幕后,并具有各种其他技巧,使其比天真地完成时要快得多。因此,它在原理上是常规克隆 ,但他们已经对其进行了调整通过他们的Web界面更有用。这就是他们让您使用GitHub的方法,而不仅仅是您自己做。)
答案 1 :(得分:2)
我所做的事情与您所做的非常相似,这是我的工作方式:
cd
到我们要克隆的目录。git clone fork-url-here
将克隆我们的fork并将其设置为remote/origin
。cd fork-name/
更改为克隆目录。git remote add upstream upstream-url-here
会将上游设置为remote/upstream
。git fetch upstream
从上游获取所有分支。git checkout master
,因为我们已经在原始/母版上,所以会收到一条消息,通知我们相同的信息。因此,一切都很好,这不是表明存在问题。git branch -a
列出所有本地+ remote/origin/*
+ remote/upstream/*
分支。其中一个将是upstream/master
(最初,我使用git branch
仅显示本地分支,这让我有些困惑,因为我在列表中看不到upstream/master
)。git merge upstream/master
,这会将upstream/master
分支合并到您当前的分支origin/master
中,从而同步到上游。您遇到的问题是因为在将上游作为远程对象添加之前,您要从上游获取它(代码块的第四行)。这将阻止您从上游获取所有分支。其他事情对我来说很好。
PS:我可以看到这是一个老问题,但是我只是想我可以帮助git初学者(像我一样),他们可能会急于使用并且无法阅读torek给出的非常好的和有益的答案。>