我在某个软件项目中,我们将代码存储在GitHub上。有一个主和开发分支的仓库。我当时在笔记本电脑上没有互联网连接,并且想开始使用其他功能,所以我做了以下工作:
git init
git remote add origin git://repo_adress
git checkout -b webapp <- created a new branch
Run Code Online (Sandbox Code Playgroud)
我添加了一些文件,文件夹等。
然后我做了:
git add .
git commit -m "something"
git push origin webapp
Run Code Online (Sandbox Code Playgroud)
我在GitHub上检查过,现在有3个分支。我想将webapp合并到开发中(不会有冲突,我在单独的文件夹中工作)。不幸的是,当我尝试这样做时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.
Run Code Online (Sandbox Code Playgroud)
现在,当我使用时git pull origin development,将显示:
From github.com:repo_address
* branch development -> FETCH_HEAD
fatal: refusing to merge unrelated histories
Run Code Online (Sandbox Code Playgroud)
我现在能做什么?我应该变基吗?
您可能应该创建一个新分支,并将您的提交放入其中。您可以与合并--allow-unrelated-histories。无论哪种方式,您都需要至少一个新提交来绑定到现有分支。
这部分是解决问题的关键:
我当时在笔记本电脑上没有互联网连接...
您在笔记本电脑上创建了一个与其他存储库没有任何关系的存储库。
Run Code Online (Sandbox Code Playgroud)git init
我假设您是在一个空目录中执行此操作的,因此它实际上创建了一个新的空存储库。即使您(矛盾地)在branch上,您的新存储库也没有提交,因此也没有分支master。也就是说,您正在上master,但master不存在!
Run Code Online (Sandbox Code Playgroud)git remote add origin git://repo_address
这将添加一个遥控器,但不会与该遥控器联系(当然这是不可能的)。结果,您的存储库继续没有提交。
Run Code Online (Sandbox Code Playgroud)git checkout -b webapp <- created a new branch
实际上,这尚未创建分支。它所做的一切就是将您从不存在的master分支变为不存在的webapp分支。
然后我做了:
Run Code Online (Sandbox Code Playgroud)git add . git commit -m "something"
当您在此空存储库中创建分支时,实际上就是在这里创建分支的第一个提交。而且,由于这是存储库中的第一个提交,因此它具有不具有父提交的特殊属性。Git将此称为根提交。
Run Code Online (Sandbox Code Playgroud)git push origin webapp
当然,这需要Internet访问,因为它会通过您提供的URL调用Git。但是,只要您有权访问,它所做的就是将您所做的提交(单根提交)完整无损地传递给其所有父项(没有父项)及其所有文件,并要求另一个Git(位于repo_address)进行更改或创建其分支名称webapp以匹配您自己的最后一次提交webapp。
Git仓库repo_address现在有一个提交图,看起来像一个更复杂的版本:
A--...--M <-- master
\
N <-- development
O <-- webapp
Run Code Online (Sandbox Code Playgroud)
我只假设了几次提交(以便我可以用单个字母而不是大的丑陋的哈希ID编号)。承诺A和O有根的提交。所有其他提交都来自A或O(但实际上没有任何派生自O,除非您在笔记本电脑上进行了多次提交)。
不幸的是,当我尝试这样做时
git pull,发生了这种情况:Run Code Online (Sandbox Code Playgroud)* [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),因此您的Git调用了另一个Git,一个位于repo_address,并下载了您没有的所有提交和分支。 -此时,是master和development工作以及那些提交。现在,您拥有与他们相同的图,只是您的Git使用远程跟踪名称而不是分支名称:
A--...--M <-- origin/master
\
N <-- origin/development
O <-- webapp (HEAD), origin/webapp
Run Code Online (Sandbox Code Playgroud)
请注意,您仍然拥有自己的分支名称,并且两个名称(您的分支名称webapp)和origin/webapp记住其分支名称的远程跟踪名称都webapp指向commit O,即新的root提交。
git pull运行的第二个命令通常是git merge。如果您未指定要合并的内容,则此合并需要一个上游设置,并且由于您没有上游且未指定要合并的内容,因此这部分失败了。
然后您运行:
Run Code Online (Sandbox Code Playgroud)git pull origin development
其中指定了要合并的内容:development您的Git正在通过远程跟踪名称记住的由他们标识的提交origin/development。(我N在一张图片的猜测中将其绘制为提交。)
该git merge命令通过查找共享提交来起作用。这是两个分支上的“最近”(无论是什么意思,确切地说是:从图形上看是直观的)提交。这两个分支之一是您当前的分支,即您HEAD所连接的分支。另一个分支是从您命名的提交(即commit)中找到的分支N。因此,Git从提交N返回其根目录commit A,以找到适当的共享提交。它还从提交返回O到其根目录,以找到共享的提交。不过O 是一个根,所以从向后走O 停在O。没有共享的提交!
这就是 Git抱怨的原因。提交附带的历史记录O包含一个提交,即提交O本身。提交背后有更多的历史N,但永远不会导致提交O。没有共享的历史记录,合并没有任何意义。
Cherry-picking包括将提交(即快照)转换为更改集以查看该提交中的“发生了什么”,然后将相同的更改集应用于其他提交。变更集只是差异列表:将一个提交变成另一个提交的说明。git diff例如,这就是显示的内容。要将提交转换为差异,Git将提交与其父级进行比较。
显然,挑选根提交有点棘手,但是Git 可以做到。它的作用是将根提交与空提交进行比较(更准确地说,是空树)。得到的DIFF由读命令:添加这个新的文件; 这里是内容。
所以,你现在可以检查出你现有的分支名称development,但有一个问题:你不要有一个名为现有的分支development。记住,你有这个:
A--...--M <-- origin/master
\
N <-- origin/development
O <-- webapp (HEAD), origin/webapp
Run Code Online (Sandbox Code Playgroud)
但是,如果您要求它签出,git checkout则会创建一个development为您命名的分支development,因为它将发现origin/development看起来足够的分支development将继续创建本地名称,指向相同的提交,然后将其设为您的HEAD:
A--...--M <-- origin/master
\
N <-- development (HEAD), origin/development
O <-- webapp, origin/webapp
Run Code Online (Sandbox Code Playgroud)
现在,您可以创建另一个新的分支,webapp2例如,这也点提交N,使用git checkout -b webapp2:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
O <-- webapp, origin/webapp
Run Code Online (Sandbox Code Playgroud)
而现在,您可以合并或樱桃采摘提交O。
我将把本节的大部分内容外包给另一个StackOverflow问题:“分支”到底是什么意思? 当我们在这里谈论“分支”时,如果我们不是指分支名称,则意味着一系列以分支尖端提交(例如M和)结尾的提交N。您将希望您的工作(以分支图结构或分支祖先术语)与这些现有分支相关。这意味着您希望您的新提交重新链接到commit N,即的当前提示development。
假设您webapp2如上所述创建,然后运行git cherry-pick webapp。Git会将提交复制O到O'适用于当前提交的新提交N。Git将通过执行所有那些git diff通过比较提交O到空树而产生的“使用这些内容创建新文件”操作来做到这一点。由于新文件不会干扰任何现有文件,因此它们应该都可以正常工作。
当Git进行新的提交时,它将webapp2向前拖动当前分支以容纳它,您将拥有:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
\
O' <-- webapp2 (HEAD)
O <-- webapp, origin/webapp
Run Code Online (Sandbox Code Playgroud)
这可能就是您一直想要的。现在,您可以删除自己的webapp,然后webapp在处的另一个Git中删除repo_address,就可以webapp2在任何地方使用,就好像您已经按照预期的方式进行了操作一样,并且如果您之前可以访问Internet,也可以这样做。
您可以改为运行git merge --allow-unrelated-histories webapp。这将告诉Git 使用相同的空树作为公共起点来进行两个比较。比较提交的内容N:添加每个文件。 比较提交的内容O:添加每个文件。 然后,Git 合并这些操作(它们都在不同的文件名上),并通过两个父项进行合并提交:
A--...--M <-- origin/master
\
N <-- development, origin/development, webapp2 (HEAD)
\
P <-- webapp2 (HEAD)
_____/
/
O <-- webapp, origin/webapp
Run Code Online (Sandbox Code Playgroud)
再一次,您可以webapp在任何地方删除。奇怪的是,您现在在您的历史记录(您的提交集合)中有这个额外的root提交O。
git merge --squash查找是什么git merge --squash,并预测它将如何离开您的存储库。与采摘樱桃相比,这有什么不同?(如果愿意,可以尝试克隆)。
| 归档时间: |
|
| 查看次数: |
2874 次 |
| 最近记录: |