TL;DR
您可能应该创建新分支并将您的提交挑选到其中。您可以与--allow-unrelated-histories 合并。无论哪种方式,您都需要至少一个新的提交来绑定到现有的分支。
长
这部分是问题的关键:
我在没有互联网连接的情况下使用笔记本电脑...
您在笔记本电脑上创建了一个与其他存储库没有关系的存储库。
git init
我假设您在一个空目录中执行此操作,因此它实际上创建了一个新的空存储库。您的新存储库没有提交,因此没有分支,即使您(相反地)在分支 master 上。也就是说,你在master,但master 不存在!
git remote add origin git://repo_address
这会添加一个遥控器,但不会联系遥控器(这当然是不可能的)。因此,您的存储库仍然没有提交。
git checkout -b webapp <- created a new branch
其实这还没有创建分支。它所做的只是将您从不存在的master 分支更改为不存在的webapp 分支。
然后我做了:
git add .
git commit -m "something"
这是实际创建分支的地方,当您在这个空的存储库中创建它的第一次提交时。而且,由于这个 是 存储库中的第一个提交,它具有它没有 parent 提交的特殊属性。 Git 将此称为 root 提交。
git push origin webapp
这当然需要访问 Internet,因为它会通过您提供的 URL 调用 Git。但是,只要您有权访问,它所做的就是将您所做的提交(单个根提交)及其所有父级(它没有)及其所有文件完整地传输,并在 repo_address 处询问另一个 Git , 更改或创建其分支名称 webapp 以匹配您自己的最后一次提交 webapp。
到目前为止一切正常,但现在您有一个包含两个根的存储库
repo_address 的 Git 存储库现在有一个提交图,看起来像是一个更复杂的版本:
A--...--M <-- master
\
N <-- development
O <-- webapp
我假设只有几个提交(这样我就可以用单个字母而不是大而丑陋的哈希 ID 对它们进行编号)。提交 A 和 O 是根提交。所有其他提交都源自A 或O(但实际上没有任何东西源自O,除非您在笔记本电脑上进行了多次提交)。
不幸的是,当我尝试git pull 时,发生了这种情况:
* [new branch] development -> origin/development
* [new branch] master -> origin/master
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull 命令只运行git fetch,然后是第二个 Git 命令。在这种情况下,它运行 git fetch origin 没有额外的约束(因为在您的存储库中没有为您的 webapp 设置 upstream),因此您的 Git 调用了另一个 Git,即 @987654350 的那个@,并下载了他们拥有的所有你没有的提交和分支——此时,是 master 和 development 工作和那些提交。现在您有了与他们相同的图表,只是您的 Git 使用 远程跟踪名称 而不是分支名称:
A--...--M <-- origin/master
\
N <-- origin/development
O <-- webapp (HEAD), origin/webapp
请注意,您仍然拥有自己的分支名称,并且这两个名称——您的分支名称 webapp,以及记住其分支名称 webapp 的远程跟踪名称 origin/webapp——指向提交 O,您的新的根提交。
git pull 运行的第二个命令通常是git merge。如果您没有指定要合并的内容,则此合并需要上游设置,并且由于您没有上游并且没有指定要合并的内容,因此这部分失败了。
然后你跑了:
git pull origin development
其中指定了要合并的内容:由他们的development 标识的提交,您自己的Git 通过远程跟踪名称origin/development 记住该提交。 (在我的猜测图中,我将其绘制为提交 N。)
git merge 命令通过查找 shared 提交来工作。这是 both 分支上的“最近”(无论它的确切含义:从图表中可以直观地看出)提交。两个分支之一是您当前的分支,即您的 HEAD 所附加的分支。另一个分支是从您命名的提交中找到的,即提交N。所以 Git 从提交 N 回到它的根,提交 A,以找到合适的共享提交。它还从提交 O 回到其根目录,以找到共享提交。但是O 是一个根,所以从O向后走在O处停止。没有共享提交!
这就是 为什么 Git 抱怨的原因。附加到提交 O 的历史记录由一个提交组成,即提交 O 本身。提交N 背后有更多的历史,但它永远不会导致提交O。没有共享历史记录,合并没有意义。
樱桃采摘
Cherry-picking 包括将提交(即快照)转换为更改集以查看该提交中“发生了什么”,然后将相同的更改集应用于其他提交。变更集只是一个差异列表:将一个提交转换为另一个提交的说明。例如,git diff 就是这样显示的。要将提交转换为差异,Git 会将提交与其父级进行比较。
显然,挑选根提交有点棘手,但 Git 可以做到这一点。它所做的是将根提交与空提交(嗯,更准确地说,empty tree)进行比较。产生的差异由以下命令组成: 添加这个新文件;这是内容。
所以您现在可以检查您现有的分支名称development,除了一个问题:您没有拥有一个名为development 的现有分支。记住,你有这个:
A--...--M <-- origin/master
\
N <-- origin/development
O <-- webapp (HEAD), origin/webapp
但是git checkout 会为你创建一个名为development 的分支,如果你要求它检查development,因为它会发现origin/development 看起来很像@ 987654385@,它将继续创建本地名称,指向相同的提交,然后将其设为您的HEAD:
A--...--M <-- origin/master
\
N <-- development (HEAD), origin/development
O <-- webapp, origin/webapp
您现在可以创建另一个新分支,例如webapp2,它也指向提交N,使用git checkout -b webapp2:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
O <-- webapp, origin/webapp
现在你可以合并或挑选提交O。
分支名称与分支
我将把本节的大部分内容外包给另一个 StackOverflow 问题:What exactly do we mean by "branch"? 当我们在这里谈论“分支”时,如果我们不是指分支名称,我们指的是一系列提交以M 和N 之类的分支提示提交结尾。您将希望您的工作(以分支图结构或分支祖先术语)与这些现有分支相关联。这意味着您希望您的新提交链接回提交N,即development 的当前提示。
如果你挑剔
假设您如上所述创建webapp2,然后运行git cherry-pick webapp。 Git 会将O复制 提交到适用于当前提交N 的新提交O'。 Git 将通过执行git diff 通过将提交O 与一棵空树进行比较而产生的所有“使用这些内容创建新文件”操作来做到这一点。由于新文件不会干扰任何现有文件,因此这一切都应该正常工作。
当 Git 进行新的提交时,它会将当前分支 webapp2 向前拖动以适应它,您将拥有:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
\
O' <-- webapp2 (HEAD)
O <-- webapp, origin/webapp
这可能是你一直想要的。现在你可以删除你自己的webapp,然后在另一个Git 中的repo_address 中删除webapp,然后在任何地方都使用webapp2,就好像你已经按照你的预期那样做了,如果你这样做了d 早点上网。
如果你合并
您可以改为运行git merge --allow-unrelated-histories webapp。这将告诉 Git 创建 两个 差异,使用相同的空树作为公共起点。一个与提交 N 的内容进行比较:添加每个文件。 一个与提交 O 的内容进行比较:添加每个文件。 Git 然后将这些操作结合起来——它们都在不同的文件名上——并进行 merge 提交, 有两个父母:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
\
P <-- webapp2 (HEAD)
_____/
/
O <-- webapp, origin/webapp
再一次,您可以在任何地方删除webapp。奇怪的是,在您的历史记录(您的提交集)中,您现在拥有这个额外的根提交 O。
练习:git merge --squash
查看git merge --squash 做了什么并预测它将如何离开您的存储库。这与采摘樱桃相比如何? (如果您愿意,可以在克隆中尝试。)