我遇到的一个问题是必须解决冗余的冲突。假设我有一个分支,它的一系列提交不断修改一个函数,而最后一次提交完全删除了这个函数。当我执行rebase master时,Git会很天真地依次应用每个提交,这意味着我需要使用master命令来解决每个提交--尽管最终这些工作都是浪费。处理这种情况的好方法是什么?也许我应该为整个分支生成一个补丁,然后对master应用它?如果是这样,有什么方法可以保留一些历史记录吗?想法,建议等等。
rebase master
s1ag04yj1#
您希望结合使用rerere-train.sh和rerere数据库的历史提交(您可能已经在/usr/share/doc/git/contrib/rerere-train.sh中使用了),这样git就可以自动使用从历史中学习到的合并冲突解决方案。
rerere-train.sh
rerere
/usr/share/doc/git/contrib/rerere-train.sh
**警告:**你盲目地使用历史字符串替换来修复冲突的合并,这实际上是在让git重写源代码。你应该在rebase之后检查所有冲突的合并。我发现gitk在这方面很好用(它只会显示冲突解决作为合并的补丁)。我对rerere只有一些好的体验,你可能就没那么幸运了。基本上,如果你的历史记录中确实包含有中断的合并(也就是说,技术上错误的合并,后来在后续提交中得到了修复),你就不想使用历史记录中的rerere,除非你想让类似的中断合并自动为你完成。
gitk
长话短说,你只要跑
git config --global rerere.enabled 1 bash /usr/share/doc/git/contrib/rerere-train.sh --all
然后是你真正想做的重定基,它应该会神奇地起作用。全局启用rerere后,以后不再需要从历史记录中学习。只有在启用rerere之前已完成冲突解决后使用rerere时才需要学习功能。附言。我找到了另一个问题的类似答案:https://stackoverflow.com/a/4155237/334451
s6fujrry2#
您可以使用git rerere功能。您必须使用git config --global rerere.enabled 1启用它,之后,您解决的每个冲突都会被存储起来供以后使用,并且解决方案会在相同的上下文中重新应用。您可以使用git rerere diff检查存储的分辨率。查看此tutorial了解更多信息。
git rerere
git config --global rerere.enabled 1
git rerere diff
wfveoks03#
为什么不在初始交互式重定基中把冗余补丁放在一起(首先把它们重新排序,这样它们就在一起了),这样你就可以清除掉序列中的“先修改后删除”部分。在这个阶段,你可以选择提交中的块(例如使用git gui)。这会给予你一个更好的序列来完成最终的干净重定基。
8yparm6h4#
(This这是我对这个问题的第二个回答。在第二次阅读时,我认为原来的问题可能与我第一次理解的问题有点不同。)我理解这个问题,因为你有一个类似于master的开发分支,通常这种类型的分支风格被称为特性分支,我绝对鼓励使用它们。你应该总是尝试保持feature分支干净。在实践中,你想要一个feature分支,如果你从来没有犯过任何错误,你会已经做了提交。对我来说,这意味着提交很多和后来的git rebase -i,以修复错误,当我后来了解到这些错误。当特性分支准备就绪时,它应该如下所示1.添加API以执行X操作1.修正角箱Z的现有API Y1.使用X和Y添加特征B(也适用于Z!)1.改进功能B:变魔术代替1.在制品1.擦拭巾21.添加API1.移动API以执行X1.添加功能B1.重新考虑后,重命名X的参数1.固定要素B1.修复X的APi1.固定角箱Z1.也为API Y固定角箱Z1.变魔术1.提交丢失的文件如果你将特性分支的基重定到最新的master分支,那么修改量很大,只有提交Fix existing API Y for corner case Z可能会导致冲突。如果该提交是修改 * 现有 * API的最小修改,那么修复冲突应该很容易。此外,只有当其他提交修改了你的最小修改所涉及的行时,才会出现冲突。如果执行要素分支和要素分支重定基而不是合并(我更喜欢的风格是重新定基,这样就可以快进,然后执行git checkout master && git merge --no-ff feature-branch-x,并在合并提交中记录整个过程-这允许保留分支的完整历史,并允许GUI工具在需要时轻松导航该特性)在将这些分支重新定基到master之前,您肯定希望执行keep your feature branches clean。从长远来看,不仅你的重定基会更容易,而且历史记录也是可读的。(从技术上讲,这会产生一个新的提交,其内容在逻辑上与挤压合并相同,但它的第二个父提交将指向具有功能分支的整个历史的提交序列。喜欢挤压合并的人可以使用第一个父提交,喜欢具有历史的人可以使用第二个父提交。你可以在这个新提交中为假想的挤压合并提交编写提交消息。)在上面的例子中,你可以使用rebase -i <old-enough-sha1>,然后将提交重新排序为3 + 4 + 6 + 8,10,1 + 2 + 5 + 7 + 9,11 + 12,其中+表示压缩。但通常更容易的做法是让提交量保持很小,然后在以后压缩其中的一些。注意,在这个例子中,即使是第10次提交也比第一次提交早,这是正常的,反映了你的实现并不完美,但这不需要保存在版本历史中。就你而言,听起来你有一个特性分支,其中多次提交添加和删除相同的东西。2将这些提交压缩为一个单独的提交(可能最后没有变化,这没关系)。只有当特性分支看起来干净的时候,才把你的特性分支的基重定为master。一定要学会使用git gui或其他一些工具,使提交修改过的 * 行 * 而不是 * 文件 * 变得容易。每一次提交都应该是一次修改一个健全的东西集合的改变。如果你添加了一个新的特性X,同一次提交 * 一定不能 * 修复现有的函数Y或添加关于Z的缺失文档。即使这些改变是对同一个 * 文件 * 做出的。对我来说,这就是Linus Torvalds说"files do not matter"时所指的东西。
master
git rebase -i
Fix existing API Y for corner case Z
git checkout master && git merge --no-ff feature-branch-x
rebase -i <old-enough-sha1>
+
git gui
4条答案
按热度按时间s1ag04yj1#
您希望结合使用
rerere-train.sh
和rerere
数据库的历史提交(您可能已经在/usr/share/doc/git/contrib/rerere-train.sh
中使用了),这样git就可以自动使用从历史中学习到的合并冲突解决方案。**警告:**你盲目地使用历史字符串替换来修复冲突的合并,这实际上是在让git重写源代码。你应该在rebase之后检查所有冲突的合并。我发现
gitk
在这方面很好用(它只会显示冲突解决作为合并的补丁)。我对rerere
只有一些好的体验,你可能就没那么幸运了。基本上,如果你的历史记录中确实包含有中断的合并(也就是说,技术上错误的合并,后来在后续提交中得到了修复),你就不想使用历史记录中的rerere
,除非你想让类似的中断合并自动为你完成。长话短说,你只要跑
然后是你真正想做的重定基,它应该会神奇地起作用。
全局启用
rerere
后,以后不再需要从历史记录中学习。只有在启用rerere
之前已完成冲突解决后使用rerere
时才需要学习功能。附言。我找到了另一个问题的类似答案:https://stackoverflow.com/a/4155237/334451
s6fujrry2#
您可以使用
git rerere
功能。您必须使用
git config --global rerere.enabled 1
启用它,之后,您解决的每个冲突都会被存储起来供以后使用,并且解决方案会在相同的上下文中重新应用。您可以使用
git rerere diff
检查存储的分辨率。查看此tutorial了解更多信息。
wfveoks03#
为什么不在初始交互式重定基中把冗余补丁放在一起(首先把它们重新排序,这样它们就在一起了),这样你就可以清除掉序列中的“先修改后删除”部分。在这个阶段,你可以选择提交中的块(例如使用git gui)。这会给予你一个更好的序列来完成最终的干净重定基。
8yparm6h4#
(This这是我对这个问题的第二个回答。在第二次阅读时,我认为原来的问题可能与我第一次理解的问题有点不同。)
我理解这个问题,因为你有一个类似于
master
的开发分支,通常这种类型的分支风格被称为特性分支,我绝对鼓励使用它们。你应该总是尝试保持feature分支干净。在实践中,你想要一个feature分支,如果你从来没有犯过任何错误,你会已经做了提交。对我来说,这意味着提交很多和后来的
git rebase -i
,以修复错误,当我后来了解到这些错误。当特性分支准备就绪时,它应该如下所示
1.添加API以执行X操作
1.修正角箱Z的现有API Y
1.使用X和Y添加特征B(也适用于Z!)
1.改进功能B:变魔术
代替
1.在制品
1.擦拭巾2
1.添加API
1.移动API以执行X
1.添加功能B
1.重新考虑后,重命名X的参数
1.固定要素B
1.修复X的APi
1.固定角箱Z
1.也为API Y固定角箱Z
1.变魔术
1.提交丢失的文件
如果你将特性分支的基重定到最新的
master
分支,那么修改量很大,只有提交Fix existing API Y for corner case Z
可能会导致冲突。如果该提交是修改 * 现有 * API的最小修改,那么修复冲突应该很容易。此外,只有当其他提交修改了你的最小修改所涉及的行时,才会出现冲突。如果执行要素分支和要素分支重定基而不是合并(我更喜欢的风格是重新定基,这样就可以快进,然后执行
git checkout master && git merge --no-ff feature-branch-x
,并在合并提交中记录整个过程-这允许保留分支的完整历史,并允许GUI工具在需要时轻松导航该特性)在将这些分支重新定基到master
之前,您肯定希望执行keep your feature branches clean。从长远来看,不仅你的重定基会更容易,而且历史记录也是可读的。(从技术上讲,这会产生一个新的提交,其内容在逻辑上与挤压合并相同,但它的第二个父提交将指向具有功能分支的整个历史的提交序列。喜欢挤压合并的人可以使用第一个父提交,喜欢具有历史的人可以使用第二个父提交。你可以在这个新提交中为假想的挤压合并提交编写提交消息。)在上面的例子中,你可以使用
rebase -i <old-enough-sha1>
,然后将提交重新排序为3 + 4 + 6 + 8,10,1 + 2 + 5 + 7 + 9,11 + 12,其中+
表示压缩。但通常更容易的做法是让提交量保持很小,然后在以后压缩其中的一些。注意,在这个例子中,即使是第10次提交也比第一次提交早,这是正常的,反映了你的实现并不完美,但这不需要保存在版本历史中。就你而言,听起来你有一个特性分支,其中多次提交添加和删除相同的东西。2将这些提交压缩为一个单独的提交(可能最后没有变化,这没关系)。只有当特性分支看起来干净的时候,才把你的特性分支的基重定为master。一定要学会使用
git gui
或其他一些工具,使提交修改过的 * 行 * 而不是 * 文件 * 变得容易。每一次提交都应该是一次修改一个健全的东西集合的改变。如果你添加了一个新的特性X,同一次提交 * 一定不能 * 修复现有的函数Y或添加关于Z的缺失文档。即使这些改变是对同一个 * 文件 * 做出的。对我来说,这就是Linus Torvalds说"files do not matter"时所指的东西。