更改未通过`git merge -squash master`撤消

时间:2018-06-24 21:31:58

标签: git

我在发布/登台分支上一直使用git merge -squash master --strategy-option=theirs。它使我(据我所知)可以将当前master分支的快照捕获到release分支中,但是没有所有数百个提交(每个都有一个新功能/错误修复)-而是将它们全部汇总为一个提交(例如“ Release 20180624”和“ Patch 1”等),因此我可以根据需要快速倒带到一个不错的发布点。

我的问题是,在git merge -squash master --strategy-option=theirs命令之后,它没有带来所有更改。我刚运行了命令,stage分支提出了一个错误编译。我比较了两个文件,在masterstage上,文件是不同的:

大师:

... loads of imports ...
import { CommentsModule } from '../comments/comments.module';
... loads more imports ...
import { routing } from './myjobs.router';
import { CommentsModule } from '../comments/comments.module';

@NgModule({
  imports: [
    ...

这是一个简单的错误,CommentsModule被导入两次。

阶段:

... loads of imports ...
import { CommentsModule } from '../comments/comments.module';
... loads more imports ...
import { routing } from './myjobs.router';

@NgModule({
  imports: [
    ...

为什么存在这种差异?几乎所有其他内容都是相同的-但现在我觉得我不能真正相信这个过程。我已经注意到了几次,通常是在随机文件中进行一次这样的更改(假设没有任何遗漏)。这次是因为它是一个不错的编译错误而导致早期发现-但我可以想象还有其他更改很难发现。我的release和stage分支不能正确反映我的代码库。

我误用了merge -squash吗?

1 个答案:

答案 0 :(得分:3)

简短的答案是git merge(尤其是自合并基础以来的合并的 变更组合)适用于面向行的差异,并且不够聪明,无法理解某些事物仅应只能导入一次。如果没有-X theirs--strategy-option theirs,则更改集不能很好地匹配,则将发生合并冲突。使用theirs可以告诉Git盲目地假设存在冲突,应该使用“他们的”版本,但是仅会影响冲突。即使没有theirs,也会造成误动作。例如,假设您提前添加了导入:

[your changes near the top of the file]
 some context here
+import { CommentsModule } from '../comments/comments.module';

假设他们决定稍后再包含此模块:

 different context here
+import { CommentsModule } from '../comments/comments.module';

Git现在可以看到在不同位置两次添加同一行的说明,因此可以做到。

常规合并和壁球合并均执行合并操作。当您或Git进行最后一次提交时,它们之间的区别就在最后。通过常规合并,新提交有两个父提交:您当前的提交,另一个提交给您的ID传递给git merge的提交:

...--o--*--o--o--...--o   <-- yourbranch (HEAD)
         \
          o--o---...---o   <-- theirbranch

成为:

...--o--*--o--o--...--o--M   <-- yourbranch (HEAD)
         \              /
          o--o---...---o   <-- theirbranch

如果没有--squash,它将变为:

...--o--*--o--o--...--o--S   <-- yourbranch (HEAD)
         \
          o--o---...---o   <-- theirbranch

请注意,“南瓜合并”提交是普通的(非合并)提交:根本不是合并!常规合并提交。 (这是一些循环逻辑:合并提交只是具有至少两个父级的提交。但这仍然是这里的关键区别。除此之外,git merge --squash是普通合并,尽管它也强制执行--no-ff--no-commit。)