没有经验的用户进行更改release
,然后合并到dev
。哦,不,合并冲突!合并状态显示他们自己的冲突文件,以及其他团队成员的所有其他修补程序。作为偏执狂和谨慎的用户,他们说:
这些不是我的文件,我是否不小心更改了它们?啊哈,我应该
discard
他们!
现在,合并提交仅包含其更改,而丢弃分支中的所有其他更改(可能需要大量工作)。他们将dev
推向上游,直到另一个团队成员发现某件事不对劲,该错误才被发现。
大多数指南建议:
git reset
git revert -m 1 <commitId>
。但是,这只会还原数据(也就是仅不幸用户的更改),不会撤消历史记录。将来进行merge
的任何尝试都将忽略丢失的更改,因为历史记录表明它们已经集成。 rebase
或reset
后跟git push origin -f
。这意味着团队的其他成员必须与强制的dev
分支同步。如果团队很大,或者没有迅速发现错误,或者存在复杂的CI工具-这将是非常痛苦的练习。 Imho在git的设计中给我带来了严重的疏忽。很少有工具可以识别这种情况或从这种情况中恢复过来。 git diff
不会显示已放弃的更改,而git revert
不会撤消那些已放弃的更改。有没有更好的方法来预防和解决此问题?
答案 0 :(得分:1)
如Linus(https://mirrors.edge.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt)所述:
还原常规提交只会有效撤消该提交 做到了,而且相当简单。但是还可以还原合并提交 撤消提交已更改的 data ,但绝对可以 合并对历史的影响不大。
因此合并将仍然存在,并且仍将被视为加入 这两个分支在一起,将来的合并将看到该合并为 最后一个共享状态-以及还原了合并带来的还原 完全不会影响。
因此,“还原”撤消数据更改,但这不是 “撤消”在某种意义上说不会撤消提交对 存储库历史记录。
好的,这可以解释为什么revert
不是有效的策略,但是我们能做什么?让我们考虑以下内容:
p---Q---r---s---M---t---u--- dev
\ /
A---B---C-------D---E feature
feature
上工作dev
无关的更改只要M存在于dev
上,就假定ABC的历史已被整合,即使AB的缺失也没有。要在不更改dev
的历史记录的情况下恢复它们,我们需要在备用历史记录(即新的提交ID)中重新创建增量。
如果提交的次数很少,则可以将每个单独的cherrypick
分别dev
拖到rebase --no-ff
上,将数据复制到新的提交ID中。但是,这不能很好地适应大型或复杂的分支历史。
下一个选择是使用feature
重新创建一个新的git checkout E
git rebase --no-ff Q
分支,可以从中合并丢失的更改。
A'--B'--C'-------D'--E' feature-fixed
/ \
p---Q---r---s---M---t---u---M2 dev
\ /
A---B---C--------D---E feature
这将创建以下内容:
p---Q---r---S-------M---t---u-----M3 dev
\ \ / /
A---B---\---C----D---E / feature
\ \ /
----M2---------- fix
原始合并M可能仅由于合并冲突而成为问题。这种方法的一个问题是,不仅您必须正确解决ABC中的原始冲突,而且现在您还需要解决DE和TU中新的冲突源。在紧急情况下,弄清楚发生了什么可能很麻烦。
squash
使用您可能熟悉的工具,一种更简单的策略是使用dev
提交(M2)正确地重新创建合并。这将创建一个新的提交ID(新历史记录),因此AB的增量可以成功地集成回主线。此方法还可以消除可能的合并冲突源,使您可以首先更正错误,然后处理上游更改。
方法:
在错误合并(M)降落之前从git checkout -b fix S
分支。
git merge --squash C
您现在拥有一个干净的状态,可以从中执行更正的合并。 squash标志会将这些更改压缩为一个提交,但更重要的是它将生成一个新的提交ID
git checkout dev
git merge fix
就像在这一点上一样,您将需要解决冲突,但是M2现在表示M原来应该包含的所有数据。现在,您可以像往常一样将其合并到开发者中了
feature
同样,可能会发生合并冲突,但是在这一点(M3)之后,您已经恢复了丢失的数据。现在,您可以按正常方式继续进行操作,例如,可以将DE从dev
合并到dev
或任何其他常规操作中。这也意味着其他团队成员无需重置其本地pull
分支,因为该分支将在下次执行TYPE Array IS TABLE OF VARCHAR2(50);
TYPE ArrayArray IS TABLE OF Array;
时恢复。