Master 恢复后 Git Merge
Posted
技术标签:
【中文标题】Master 恢复后 Git Merge【英文标题】:Git Merge after Master has been reverted 【发布时间】:2021-12-27 18:14:51 【问题描述】:我在一个名为 BR1 的功能分支中工作,该分支从 master 分支出来。
此时master和我的分支有文件a.js
,内容为:
1: console.log(`Hello Duck`);
在创建 BR1 大约 20 天后,master 恢复到过去的提交。现在master里面a.js
的内容改回了:
1: console.log(`Hello Dog`);
在此期间,我在分支中更改了a.js
,添加了更多代码:
1: console.log(`Hello Duck`); // this line was not changed
2: if (foo === bar) return; // added this line.
如何将我的 BR1 分支合并到 master,避免将内容 a.js
从我的分支替换到 master。我想在我没有更改/添加的行上保留主内容。我想要这样的东西:
1: console.log(`Hello Dog`);
2: if (foo === bar) return; // add this line.
【问题讨论】:
【参考方案1】:在 Git 中,单词 revert 与单词 reset 具有不同的含义,并且它们不可互换。您revert 通过创建一个与您正在恢复的提交相反的新提交,有效地撤消更改。当您重置一个分支时,您更改了该分支指向的提交,如果您将其向后移动到该分支上较旧的提交,那么之后的所有提交都会从该分支中有效地删除。
鉴于这些定义,没有任何意义:
master 被恢复到过去的提交。
我假设你的意思是:
master 被重置为过去的提交。
为什么这很重要?
如果更改相关行的提交已在master
上还原,那么当您将分支合并到master
时,您将遇到冲突,您可以通过选择解决您想要的确切结果(采用较旧的第一行和较新的第二行)。但由于master
被重置,您的分支在 Git 看来是所有较新的更改,因此 Git 将选择您的所有更改而不提示解决冲突。
那你该怎么办?
你可以做很多事情,其中两个是:
经过进一步考虑,不要选择此选项。 只需将文件的第一行更改为它在当前 此选项的问题是您将使用重置带回从 master
分支上的样子,然后将其提交到你的带有标题消息的分支,例如“由于分支重置而更新”,并且可能在提交消息详细信息中提供更多信息。现在,当您在分支中合并时,您不会影响由于重置而未完成的行。master
删除的提交,大概是故意删除的。
执行此操作: 重建您的分支,就好像它脱离了当前 master
的样子。有多种方法可以做到这一点,但从概念上讲,您从当前的 master
创建一个新分支,然后将您的每个提交挑选到该分支上。对于需要解决的第一个更改,您将在相关线路上遇到冲突。您还可以使用类似于以下内容的方式对您的分支进行“花式”变基:
git rebase --onto current-master old-master
使用 rebase,您还需要解决第一行中的冲突。
旁注:这是不赞成重置共享分支(例如 master
)的原因之一,因为它可能会弄乱基于它的所有分支,这正是发生在你身上。
【讨论】:
【参考方案2】:就去做吧。您必须告诉 Git 该对的正确结果,它会(正确地)注意到相邻线的变化,并要求人工判断它们是否以及如何交互。在像这样的“他们不这样做”的情况下,这可能会令人惊讶,但关键是,他们经常这样做,而 Git 假设他们不这样做是一个非常糟糕的决定。
熟练使用这些工具,像这样的小问题需要大约两秒钟才能解决。
git init testmerge; cd $_
echo Hello Duck >t1; git add .; git commit -m duck
git checkout -b br1
echo new line >>t1; git commit -am newline
git checkout master;
echo Hello Dog >t1; git commit -am dog
git merge br1
并且 Git 报告了一个冲突,邻接的行发生了变化。进行冲突提交的顺序无关紧要,重要的是两个提示对重叠或邻接线的更改。
【讨论】:
我已经尝试在我的分支和 master 之间进行简单的合并,但不幸的是无法按预期工作。因为我的分支是最新的,然后是 master,它会覆盖我对 master 所做的更改。在上面的示例中,第 1 行的最终结果将是console.log(
Hello Duck);
而不是我想要的 console.log(
Hello Dog);
。
那么有件事你没有告诉我们。 Git 的合并不是这样的。
啊。我知道了。我认为@TTG 是对的,你没有恢复旧的更改,添加了一个新的提交来撤消该更改,你将标签重新挂在旧的提交上。当您知道自己在做什么时,这是一件非常有用的事情。查找git log --oneline --graph --decorate
。我有git config --global alias.lgdo '!f() git log --graph --decorate --oneline "$@---all"; ; f'
,我可以说git lgdo
看看历史是什么样子,或者git lgdo master br1
看看这些分支的历史是什么样的。以上是关于Master 恢复后 Git Merge的主要内容,如果未能解决你的问题,请参考以下文章
恢复后 Git 在命令栏中显示 (master|REVERTING)