如何拉出不同的远程分支并合并冲突

问题描述 投票:0回答:1

我使用了seed来启动我的项目并添加了更改,首先是克隆种子项目,编辑并将remoteorigin更改为boilerplate,现在我已经让项目工作在master上我添加了我自己的repo remote 。但是我希望为该项目的新版本设置一个分支,并且样板库repo已经有一个远程分支phaser3,我想基本上拉动和替换冲突,以便我可以开始迁移到新版本。继承人我试过的:

dir git:(master) git fetch boilerplate phaser3
From https://github.com/lean/phaser-es6-webpack
 * branch            phaser3    -> FETCH_HEAD
dir git:(master) git checkout phaser3
Branch 'phaser3' set up to track remote branch 'phaser3' from 'boilerplate'.
Switched to a new branch 'phaser3'
dir git:(phaser3) git pull
Already up to date.
dir git:(phaser3) git pull --rebase
Already up to date.
Current branch phaser3 is up to date.

所以我似乎很清楚我已经获得了我的本地phaser3分支来跟踪boilerplate/phaser3,但是我现在如何引入更新的phaser3 package.json以及两个phaser3分支之间不同的其他文件?

git git-remote boilerplate
1个回答
0
投票

这里好像没有错。尽管如此,你的输出中仍有一些可疑的东西,这表明你可能正在运行Git 1.8.3或更早版本,或者可能没有。 (您可以轻松地使用git --version进行检查。如果您的Git是2.0之前的版本,则可能需要升级。截至此答案,当前版本为v2.21。)

有趣的是这一点:

➜  dir git:(master) git fetch boilerplate phaser3
From https://github.com/lean/phaser-es6-webpack
 * branch            phaser3    -> FETCH_HEAD

将此与我今天下午在我的Linux存储库中的git fetch origin master时得到的结果相比较:

$ git fetch origin master
remote: Counting objects: 235, done.
remote: Compressing objects: 100% (160/160), done.
remote: Total 235 (delta 120), reused 124 (delta 71)
Receiving objects: 100% (235/235), 273.62 KiB | 230.00 KiB/s, done.
Resolving deltas: 100% (120/120), done.
From git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
 * branch                      master     -> FETCH_HEAD
   9e98c678c2d6..54c490164523  master     -> origin/master

除了额外的冗长(计数,压缩,接收等),最后两行在一个非常重要的方面是不同的:

 * branch                      master     -> FETCH_HEAD
   9e98c678c2d6..54c490164523  master     -> origin/master

他们表明我的Git已经为origin/master写了一个新的哈希ID。具体来说,在我运行git fetch之前,我得到了:

$ git rev-parse origin/master
9e98c678c2d6ae3a17cb2de55d17f69dddaa231b

我跑了git fetch之后,得到了:

$ git rev-parse origin/master
54c490164523de90c42b1d89e7de3befe3284d1b

这是因为git fetch origin master更新了我自己的Git存储库中的两个关键项。其中一个是我的远程跟踪名称refs/remotes/origin/master,通常缩写为origin/master。另一个是特殊文件.git/FETCH_HEADgit fetch总是根据你告诉它取的内容以及它从其他Git获得的内容来编写。

您的输出显示您的Git仅更新其中一个项目,即文件.git/FETCH_HEAD。但这可能是正常的,而不是旧版Git的标志,因为如果我之后立即重新运行相同的git fetch,则会发生这种情况:

$ git fetch origin master
From git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux
 * branch                      master     -> FETCH_HEAD

这看起来和你自己的输出一样。所以我怀疑你的git fetch基本上什么也没做,就像我的第二个git fetch,因为没有任何关系。这将导致您所看到的其余行为。

What's going on here

了解git fetch正在做什么的关键在于意识到分支名称对Git不是很重要。对Git来说重要的是每次提交。每个提交都由其哈希ID唯一标识,该哈希ID看起来是随机的,但实际上是其内容的加密校验和。

Git提交存储所有文件的快照,以及一些元数据 - 有关提交的一些数据。元数据包括进行提交的人员的姓名和电子邮件地址,他们何时提交(时间戳),他们为什么做(他们的日志消息),以及 - 至关重要 - 提交的父哈希ID。

这是来自此特定存储库的示例提交。它的哈希ID是d1f0301b3333eef5efbfa1fe0f0edbea01863d5d

$ git cat-file -p d1f0301b3333eef5efbfa1fe0f0edbea01863d5d | sed 's/@/ /'
tree 86c897e94952090eee579ed47f49cc7006c41fd6
parent 6b4703768268d09ac928c64474fd686adf4574f9
author Thomas Gleixner <tglx linutronix.de> 1533300299 +0200
committer Thomas Gleixner <tglx linutronix.de> 1533302341 +0200

genirq: Make force irq threading setup more robust

The support of force threading interrupts which are set up with both a
primary and a threaded handler wreckaged the setup of regular requested
threaded interrupts (primary handler == NULL).

[snip]

这不是我们通常查看提交的方式 - 大多数情况下,我们可能会使用git showgit log,以及那些比较提交到早期提交的内容,以便我们可以看到两个快照中的不同之处。这就像比较今天多么温暖或下雨到昨天多么温暖或下雨:它告诉我们改变了什么,这对我们来说有时比绝对状态更重要。但这确实显示了提交中的内容:它有一个树(带有一些内部Git哈希ID),一个带有另一个提交的哈希ID的父,以及作者和提交者和日志消息。 (有些提交有更多东西。)树是Git存储快照的方式。 parent行告诉我们在此提交之前提交了哪个提交。

结果是,给定一些Git提交哈希ID,Git总能找到提交之前的提交。实际上,父行指向另一个较早的提交。因此,如果我们有一些长链提交:

... <-F <-G <-H ...

我们可以选择其中一个提交,然后按箭头向后执行前一个提交:从HG,再到F,依此类推。

这里的问题是这些哈希ID看起来完全是随机的,并且部分取决于什么时间,到了确切的秒,有人制作它们。例如,Thomas Gleixner在时间1533300299 +0200上提交了上述提交.1所有这些细节都包含在提交哈希ID中。这意味着我们无法知道哈希ID是什么 - 它实际上是随机的。那么我们如何知道哪个提交是最新的提交?

答案是Git通过让我们创建分支名称来帮助我们。我们告诉Git:将最新/最新提交的哈希ID存储在某些名称下,如masterphaser3。鉴于ID,Git可以找到提交本身。该提交存储父ID,因此Git也可以找到父ID。父存储另一个父ID - 祖父母,就像这个提交一样 - 所以Git可以找到祖父母,并且该提交存储另一个父ID,依此类推历史。

事实上,历史只不过是从每次提交到其父级所发现的提交集。从一些起点和后退工作中访问的提交是Git存储库中的历史记录。起点是存储库中的所有名称:分支名称,标签名称(如v2.1)和远程跟踪名称(如origin/masterboilerplate/phaser3.2)。


1Well,那是他撰写(原始版本)提交时,但后来他在1533302341,34分钟和2秒后提交了提交。

2A存储库可以,并且在诸如git rebasegit commit --amend之类的各种操作之后,将包含本步行未访问的提交,所有提交都可通过从某个名称进程开始到达。这些剩余或垃圾提交最终被Git的垃圾收集器git gc清理并抛弃。请注意,git gc至少会执行许多其他内务管理和提高性能的内容,或旨在提高性能的内容。这一切都是自动完成的 - 通常无需手动运行。


Checkout creates branches, sometimes

你跑了git checkout phaser3,你的Git说:

Branch 'phaser3' set up to track remote branch 'phaser3' from 'boilerplate'.
Switched to a new branch 'phaser3'

通常,当你说git checkout somebranch时,Git所做的就是在您的存储库中查找名为somebranch的分支。该分支名称标识应被视为分支尖端的最新/最新提交。您的Git提取提交到索引和工作树中,以便您可以看到它并使用它。

但有时候,你告诉Git检查一个分支,你没有那个分支。而不仅仅是失败 - 这仍然可能发生:

$ git checkout nosuchbranch
error: pathspec 'nosuchbranch' did not match any file(s) known to git

你的Git首先列出你自己的分支,la git branch

$ git branch
* master

您要求的名称不在列表中,但Git尚未准备好放弃。现在它会检查所有远程跟踪名称,您可以使用git branch -r列出这些名称。这样做的结果取决于你拥有哪些遥控器 - 大多数人在他们的存储库中只有一个名为origin的名字 - 以及你的Git从这些遥控器中记住的名字:

$ git branch -r
  origin/develop
  origin/feature2
  origin/master
  upstream/master
  upstream/develop

我问nosuchbranch,这些都不是那样的。但是,如果我要求feature2怎么办?

Git将扫描这些,并且恰好有一个名称匹配feature2,即origin/feature2。所以我的Git会说:啊哈,你要我用feature2作为提交来创建一个新的origin/feature2!现在我可能有:

... <-H <-I <-J   <-- feature2 (HEAD), origin/feature2

名字feature2origin/feature2都记住了提交J的哈希ID。

请注意,在这种特殊情况下 - 我没有develop,但originupstream都有一个 - 如果我运行:

git checkout develop

我的Git会放弃,因为它不知道它是否应该从developorigin/develop制作一个新的upstream/develop。即使这两个都识别相同的提交 - 说,提交L,我没有在图中绘制 - 我的Git不知道这两个中的哪一个用作我的新develop的上游设置。我在这里可以做的是:

git checkout --track origin/develop

这告诉我的Git:使用origin/develop,制作一个新的develop,其中develop更新,并推动,origindevelop

我们在这里走得很快,并没有详细说明这一切是如何工作的,但我在这里再次提到它设置了新创建的分支的上游设置。分支的上游是当你运行git status时Git决定说“前进”和/或“后面”的方式,以及如果你运行没有参数的git mergegit rebase,Git如何知道要使用哪些提交。如果你不提供额外的参数,上游决定git pullgit push将做什么,当你有多个遥控器时,哪个远程git fetch将使用。因此上游设置非常有用。

Summary

git pull --rebase什么也没做,因为没有新的提交:你的图形看起来像这样,当我想在StackOverflow上绘制提交时:

...--G--H   <-- phaser3 (HEAD), boilerplate/phaser3

或者像这样:

...--G--H   <-- boilerplate/phaser3
         \
          I   <-- phaser3

git rebase所做的工作是复制你没有的提交 - 例如在这个图中提交I - 到他们最后一次提交之后的新提交。在这种情况下,这将复制IH之后的新提交,而不是I现在,但I已经在H之后,所以没有必要做任何这样的复制。 (并且在两个名称指向相同的提交H的情况下,没有提交复制,这也意味着没有工作要做。)

phaser3的上游是boilerplate/phaser3boilerplate这个名字本身通常只是https://github.com/lean/phaser-es6-webpack的一个简称; Git称之为远程。

https://github.com/lean/phaser-es6-webpack有一个完整的Git存储库;它有四个分支。您的存储库已复制其phaser3分支 - 存储在该名称中的哈希ID c9584e75521a3b94d4f883a246aad134b83dc12d,即您自己的远程跟踪名称boilerplate/phaser3

git fetchgit push命令是将提交从一个存储库传输到另一个存储库的命令。通常,发送方发送接收方尚未提交的提交,因此最终接收方拥有发送方拥有的所有内容,如果已经拥有发送方没有的内容,则可能更多。从发送方发送到接收方的提交后,接收方现在需要更新一些名称或名称以记住新提交。

当使用git fetch时,接收器 - 你 - 或者更确切地说,你的Git-更新你的远程跟踪名称。你拿他们的名字,phaser3,并用你的远程名称boilerplate作为前缀,并在它们之间加上斜线。这给了你boilerplate/phaser3作为记住他们的提交的方式。

当使用git push时,发送者 - 你再次 - 负责要求接收者在接收者中设置一些名字。您可以选择要求他们设置的名称。如果这个名字是,例如,phaser3,你要求他们改变他们的phaser3。他们没有远程跟踪名称:这里没有quantum_spaghetti/phaser3。你要求他们改名。因此,一般来说,您应该确保无论您发送了什么新提交,这些新提交都将其现有提交作为历史记录的一部分。

© www.soinside.com 2019 - 2024. All rights reserved.