t_k*_*lah 2 git git-merge git-cherry-pick
我最近在 git merge 方面遇到了很多麻烦。我发现,如果它是一个只有很少更改的小分支,那么一切都会按预期工作,但是每当我合并一个已触及文件分配并提交数天/数周的分支时,我发现运行“git mergebranch”时所有的提交没有被应用,所以我必须回顾并确定哪些提交没有被应用并挑选它们。这似乎是错误的,但我不太确定我的工作流程出了什么问题,使得我不得不这样做。
如何确保合并时“应用”指定分支中的所有更改?
任何帮助,将不胜感激!
编辑 -
对于那些想知道 git rebase 本质上是我正在寻找的东西的人来说。这并不是说我的更改被覆盖,也不是其他人所说的任何内容,我的分支远远落后于 master,而且可能是我使用 rebase -interactive 来压缩提交,我认为 git 在某种意义上失去了对已更改内容的引用。在我的分支上进行 Git rebase,检查 master 然后将我的分支合并到 master 修复了所有更改未通过合并的问题。
2020 年 12 月更新 -
我已经更新了我的合并流程,专门使用在线 github gui 并创建拉取请求,这完全解决了我曾经遇到的所有合并问题。
合并永远不会“应用所有提交”\xe2\x80\x94,这不是它的工作原理。
\n\n我们在这里需要小心一些,因为git merge并不总是合并,但是当您有一系列如下所示的提交时,通常会发生合并:
I--J <-- our-branch (HEAD)\n /\n...--G--H\n \\\n K--L <-- their-branch\nRun Code Online (Sandbox Code Playgroud)\n\n在这里,您已J签出提交,因为您已our-branch签出分支。因此您的索引和工作树与 commit 中的快照匹配J。然后你运行:
git merge their-branch\nRun Code Online (Sandbox Code Playgroud)\n\nGit 找到L名称指向的commit their-branch。犯罪L 还包含快照,但合并的工作是以某种方式组合更改。
为了看到变化,Git 总是需要比较两个提交。这两次提交之间的不同之处就是不同的\xe2\x80\x94a 更改。但直接比较J和L是行不通的。
要获得有用的更改,git merge必须首先找到最佳的共享提交,从our-branch(commt J) 开始并向后工作,以及从their-branch(commit L) 开始并向后工作。Git 称其为合并基础。在这里,合并基础提交清晰可见:它是 commit H。
所以 Git 现在实际上运行了两个 git diffs:
git diff --find-renames <hash-of-H> <hash-of-J> # what we changed\ngit diff --find-renames <hash-of-H> <hash-of-L> # what they changed\nRun Code Online (Sandbox Code Playgroud)\n\n第一个变更集生成指令,如果将其应用于 commit (中的快照)H,将生成 commit J。第二个产生的指令将更H改为L.
现在要做git merge的就是将这两套指令结合起来。如果我们更改了文件F,而他们没有更改,Git 会使用我们对F 的更改,这实际上只是提交中的文件FJ。如果他们更改了其他文件而我们没有更改,Git 将使用他们的文件。只有当我们都触碰同一个地方时文件时,Git 才真正需要努力。
不管怎样,Git 将组合的更改应用于在以下位置找到的文件:H以构建新的索引和工作树。在我们都接触相同文件的情况下,Git 工作得更努力,并且确实合并了更改。如果它们发生冲突,Git 会在索引和工作树中留下混乱,我们必须清理这些混乱,然后自己完成合并。否则 Git 会继续自行进行新的提交。
无论哪种方式,一旦我们完成或 Git 完成,新提交就会有一个快照,就像任何其他提交一样。它与任何其他普通提交只有一点点不同:它不是仅指向commit,J而是指向 commitsJ 和 L两者:
I--J\n / \\\n...--G--H M <-- our-branch (HEAD)\n \\ /\n K--L <-- their-branch\nRun Code Online (Sandbox Code Playgroud)\n\n进行 commit 后M,该名称our-branch现在指向新的合并提交,该提交又指向J往常(作为其第一个父级),但也指向L(作为其第一个父级),但也指向(作为其第二个)。
第一父母和第二父母的年龄影响未来合并。现在这并不重要,但让我们继续向每个分支添加两个提交:
\n\n I--J N--O <-- our-branch (HEAD)\n / \\ /\n...--G--H M\n \\ /\n K--L---P--Q <-- their-branch\nRun Code Online (Sandbox Code Playgroud)\n\n如果您现在运行git merge their-branch,Git 首先会执行与上次相同的操作,即查找合并基础。合并基础是两个分支上最好的共享提交\xe2\x80\x94a提交\xe2\x80\x94,但这次不是提交。我们从、、、-and- 、-and-等开始并向后推算。同时,我们从 开始并向后进行:, ,HOONMJLIKQQPL、 等等。
但这一次,提交L是在两个分支上。所以现在 commitL是合并基础。LGit 会比较和中的快照,O看看我们更改了什么,然后比较 和 中的快照L,Q看看它们更改了什么。
因此,最终,现在合并的结果取决于提交图中记录的内容(当时合并的内容)以及三个关键提交中每个提交的快照。这三个提交是:
\n\nHEAD) 提交;如果您想查看 Git 找到的提交,请git merge-base使用以下--all选项运行:
git merge-base --all our-branch their-branch\nRun Code Online (Sandbox Code Playgroud)\n\n这应该打印一个提交哈希 ID。如果是这样,那就是 Git 使用的合并基础。(如果它打印多个哈希 ID,那么您将处于一种棘手的合并情况,我们需要更多的单词。:-))
\n\n如果您想了解为什么会得到这样的结果,请找到合并基础,然后git diff自己运行这两个命令。(您需要将其输出重定向到某处,和/或--name-status首先使用。)
| 归档时间: |
|
| 查看次数: |
6456 次 |
| 最近记录: |