繁体   English   中英

如何在创建的提交上将分支合并到 master

[英]how to merge branch into master on the created commit

我有这个场景,我从 master 创建了一个分支 A,其中 master 负责人在1234提交 id

现在一些开发人员将更多的分支和提交推送到 master 中,现在 master 负责人在789提交 id 上。

是否可以在提交1234时将分支 A 合并到 master 中?

不要试图把这个比喻推得太远(因为它会崩溃),但这有点像问你是否可以将你的 package 放在中国的货船上,因为船在洛杉矶的港口。 你可以,但你得先把船弄回中国。

让我们看看 Git 是如何工作的,而不是上面的笨拙的类比。 Git 都是关于提交的,而且——正如你在这里正确描述的——这些提交被编号 不过,这个数字并不是简单的连续计数数字——例如,提交 #52 后面没有提交 #53——而是它们是大的、丑陋的、看起来随机的 hash ID。 所以我喜欢用单个大写字母来表示它们:

...--G--H   <-- master

在这里,名称master指向提交H Hmaster上的最新提交 提交H本身向后到达较早的提交G ,后者向后到达另一个较早的提交,依此类推。

在您的情况下,您创建了一个新名称也指向提交H ,然后进行了一些新提交:

          I--J   <-- your-branch
         /
...--G--H   <-- master

不幸的是,从那时起,其他人master添加了更多提交,如下所示:

          I--J   <-- your-branch
         /
...--G--H
         \
          K--L   <-- master

您现在询问是否使用git merge

合并是关于合并工作

当我们确实使用git merge时,我们这样做是因为我们想合并工作 也就是说,你从提交H开始——一些特定的文件集,永远存储在一个带有一些丑陋的大 hash ID 的提交中。 您更改了一个或两个文件并进行了新的提交,它得到了一些我称之为I的其他大而丑陋的随机 ID,并且可能更改了另一个或两个文件(或相同的文件或两个)并进行了另一个提交J . 所以在HJ之间,你做了一些工作,导致一些文件发生了一些变化。

Git 可以通过将提交H中的快照(从您开始的所有时间冻结的文件集)与您最近提交中的快照进行比较,向您展示您所做的(总结为一组大的一次性更改), I 这将有如下指令:在文件main.py中,删除第 47 行,并在第 300 行之后添加一些行

Git 还可以通过比较H中的快照中的内容(注意此快照在两个分支上共享)与提交Kmaster上的最新快照中的内容,向您展示其他人做了什么。 这可能包含更改 README.md 中的第 7 行README.md类的指令,以及诸如main.py中的第 100 行添加一行的指令

git merge可以为您或任何人做的就是结合这些更改 也就是说,如果他们接触README.md而你没有接触,Git 将保留他们的更改。 如果您触摸了Documentation/info.md而他们没有,Git 将保留您的更改。 如果您和他们都修改main.py , Git 将尝试保留对该文件的两组更改

如果 Git可以自己组合所有这些更改,则 Git 将自己进行一个新的提交。 这个新的提交将包含来自H中快照的所有文件(通用起点)作为其快照,并应用组合更改,以便 Git 保留您的更改并添加他们的更改,或者 - 如果您更喜欢查看它方式 - 保留他们的更改并添加您的。 结果都是一样的,看起来像这样:

          I--J
         /    \
...--G--H      M
         \    /
          K--L

我在这里留下的是哪个分支拥有新的提交M 有两个名称——master 和your-branch master并且 Git 只会更新这两个名称之一,以便它指向新的提交M 另一个名称将继续指向提交J或提交L (无论它之前指向哪个)。

我还省略了另一个细节,这有时确实很重要:因为提交M两个反向链接,或者parents ,指向提交JL ,所以这两个中的一个首先出现。 另一个是第二个,尽管对于 Git,这只是“不是第一”。 稍后, --first-parent标志有时对于挑选“第一个”父级很有用。 无论您如何进行合并, M中的快照都是相同的,但是第一父级的选择取决于您git switch到哪个分支,以及您给git merge的名称:

git switch master
git merge your-branch

给我们:

          I--J   <-- your-branch
         /    \₂
...--G--H      M   <-- master
         \    /¹
          K--L

也就是说, master是指向M名称,而第一个父级现在是L

这通常是大多数人想要做的——除非他们想使用git rebase

是否可以在 [shared] 提交时将 [my branch] 合并到 master 中?

不完全是,因为无论你做什么, master最终都需要指向除H之外的其他提交。

可以“弹出”提交KL ,如下所示:

          I--J   <-- your-branch
         /
...--G--H   <-- master
         \
          K--L   [abandoned]

这样做的问题是提交KL现在丢失了 它们并没有消失——它们仍然在存储库中——但是 Git 通过以分支名称开头来查找提交。 用于查找提交L的名称master L , Git 可以向后工作到K

Git无法继续工作。 Git 总是向后工作。 因此,一旦您将master向后移动两步,指向H , Git 就再也找不到K了。 即使 Git可以找到K ,也无助于找到L 所以这两个提交现在被“放弃”了。 丢掉了他们的工作 这不是合并的目的:合并有助于在添加您的工作时保留其他人的工作,或者等效地,在添加其他人的同时保留您的工作

变基

无需赘述,变基背后的想法是我们希望将一些提交复制到一些新的和改进的提交中。 在这种特殊情况下,您可能希望接受您认为非常好的IJ提交,并通过进行两次的提交来“改进”它们——由于目前还没有明显的原因,我们将其称为I' (I- prime) 和J'很像IJ

新的和改进I'与原来的I之间的区别在于两部分:

  • 新的I'将不向后链接到H ,而是链接到K
  • 新的I'作为它的快照,不是H中随您的更改而修改的快照,而是K中随您的更改而修改的快照。

I'rest将与I完全相同,包括提交日志消息 现在让我们画出I'

          I--J   <-- your-branch
         /
...--G--H
         \
          K--L   <-- master
              \
               I'  <-- temporary-branch

(The underlying Git command that produces I' from I is git cherry-pick . We have to have Git do this on a temporary branch , because Git needs to be able to find all the commits, including both the old ones and the new ones正在构建。rebase 命令隐藏了这种复杂性的大部分,但是因为 Git 在某些事情上很糟糕,所以有时你会看到这一切。)

一旦 Git 复制了II' ,我们需要让 Git 复制JJ'

          I--J   <-- your-branch
         /
...--G--H
         \
          K--L   <-- master
              \
               I'-J'  <-- temporary-branch

一旦将your-branch上的所有提交复制到新的临时分支,然后我们将 Git 从提交J中“剥离分支名称” your-branch并将其粘贴到提交J' — 刚刚制作的最后一个副本 Git —并丢弃临时名称:

          I--J   [abandoned]
         /
...--G--H
         \
          K--L   <-- master
              \
               I'-J'  <-- your-branch

因为 Git 按分支名称查找提交,所以如果我们现在查看这个存储库,看起来好像我们等到提交L存在,然后才开始工作并生成提交IJ 我们将看到提交I'J' ,而不是IJ ,但除非我们记住实际的 hash ID——而且没有人这样做过——否则我们不会注意到我们现在正在查看两个不同的提交。 (Git 会知道。Git 查看原始的 hash ID。但我们会忘记,因为这是人类所做的。)

是否以及何时重新设置取决于您

因为 rebase用新的提交替换了旧的提交(新的并且据说是改进的),所以它并不总是合适的。 特别是,如果你已经将你的IJ提交给了其他人,并且他们依赖于他们——包括他们的 hash ID——然后说“把它们扔掉,改用这些新的和改进的”会让他们做额外的工作. 有时这很好。 (例如,如果他们已经同意这样做,那也没关系。)有时不是。

但是,如果您从未将这些提交给任何其他人,他们甚至不会知道您这样做了。 所以对于那个特殊的情况——“私人”提交——只要你知道你在做什么,rebase 是安全的。

变基的好处是,最后,Git 的历史“看起来更简单”,人们可以用更少的精神负担来思考它。 缺点是它不是真正发生的事情:如果你在 rebase 期间破坏了某些东西,它可能很难调试,这是一个谎言。 是一个善意的谎言让事情变得更好,还是一个丑陋的大谎言导致死亡和毁灭? 我们不知道,您可能还不知道,直到您尝试一下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM