Git是最流行的代码版本控制系统,这一系列文章介绍了一些Git的高阶使用方式,从而帮助我们可以更好的利用Git的能力。本系列一共8篇文章,这是第4篇。原文:Merge Conflicts: What They Are and How to Deal with Them[1]
合并冲突……没有人会喜欢,有些人甚至害怕冲突。但是使用Git时,特别是需要与其他开发人员合作时,冲突是不可避免的。大多数情况下,合并冲突并不像想象的那么可怕。在“Git进阶”系列的第四部分中,我们将讨论冲突何时会发生,实际是什么,以及如何解决。
Git进阶系列:
创建完美的提交 Git中的分支策略 基于Pull Request实现更好的协作 合并冲突(本文) Rebase vs Merge 交互式Rebase Git中的Cherry-pick提交 用Reflog恢复丢失的提交
何时以及为什么会发生合并冲突
从名称就可以看出来: 将来自不同来源的更改集成(或“合并”)到当前工作分支时,就可能会发生合并冲突。请记住,集成并不局限于合并分支。冲突也可能发生在rebase或交互式rebase过程中、在cherry-pick(从一个分支选择某个提交应用到另一个分支)过程中、在执行git pull
时,甚至在重新加载暂存区的内容时。
所有这些操作都执行某种类型的集成,这就是合并冲突可能发生的时候。当然,并不意味着这些操作每次都会导致合并冲突,那么到底什么时候会发生冲突呢?
实际上,Git的合并功能是其最大的优势之一: 分支合并在大多数时候都能完美工作,Git通常能自己解决问题,知道如何集成变更。
但也有发生了相互矛盾的变化的情况,那时候技术根本无法决定什么是对的,什么是错的,这时就需要人类做出决定。例如,当同一行代码在两个不同分支的两次提交中被更改时,Git无法知道哪一次更改才是对的。另一种不太常见的情况是,一个文件在一个分支中被修改,而在另一个分支中被删除了。Git会问你该做什么,而不是猜测该怎么做。
怎样才能知道何时发生了合并冲突
那么,如何才能知道发生了合并冲突?不用担心,如果合并或rebase失败,Git会立即告诉我们,也会对如何解决这个问题提出建议。例如,如果提交的更改与其他人的更改发生了冲突,Git会在终端通知我们,并告诉我们自动合并失败了:
$ git merge develop
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
可以看到,这里发生了一次冲突,Git立即报告了问题。即使错过这条消息,也会在下次输入git status
时提示有冲突。
如果使用的是Tower这样的Git桌面GUI,会确保不会忽略任何冲突:
在任何情况下都不用担心没有注意到合并冲突!
如何撤销合并冲突并重新开始
不能忽略合并冲突,相反,必须在继续工作之前处理,基本上有以下两种选择:
-
解决冲突 -
中止或撤销导致冲突的操作
在开始解决冲突之前,我们简要谈谈如何撤消和重新开始(知道有可能恢复,就让人非常放心)。在很多情况下,只需要简单添加--abort
参数,比方说git merge --abort
和git rebase --abort
,这个命令可以撤消合并/rebase并恢复到冲突发生之前的状态。
当我们解决冲突时,即使发现自己进入了死胡同,仍然可以撤消合并。这可以给我们信心,真的不会搞砸,我们总是可以中止,返回到干净的状态,然后重新开始。
Git中的合并冲突到底是什么样的
让我们看看真正的冲突是什么样的。是时候揭开这些小东西的神秘面纱,更好的了解它们了。一旦理解了合并冲突,就没什么可担心的了。
看看当前存在冲突的index.html
文件的内容:
Git很好的标记了文件中有问题的区域,通过<<<<<<<和>>>>>>>包围。第一个标记之后的内容来自我们当前的工作分支(HEAD
),七个等号(=======)的行分隔了两个冲突的更改,后面的内容显示来自另一个分支的更改(在例子里是develop
)。
我们的工作是清理这些行并解决冲突,无论是通过文本编辑器、IDE、Git桌面GUI,或者通过Diff & Merge工具。
如何解决Git冲突
使用哪种工具或应用程序来解决合并冲突并不重要,当完成合并后,文件看起来必须与期望的完全一样。如果只有你一个人,可以很容易决定放弃哪些更改。但是,如果有冲突的更改来自其他人,可能必须在决定保留哪些代码之前与他们进行交谈。也许保留你的,也许保留别人的,也许是这两者的结合。
清理文件并确保包含真正想要的内容的过程并不需要任何魔法,可以简单的通过打开文本编辑器或IDE并进行更改来做到这一点。
然而,有时这并不是最有效的方法,专用工具也许可以节省更多时间和精力。例如,在解决合并冲突时,可以利用各种各样的Git桌面GUI。
以Tower为例,它提供了一个专用的“冲突向导”,从而使本来抽象的情况更加直观,有助于更好的理解变化来自哪里,发生了什么类型的修改,并最终解决问题:
特别是对于更复杂的冲突,手头有一个专用的Diff & Merge工具是很好的,通过高级功能,如特殊格式和不同的表示模式(例如并排,合并在一个列中,等等),可以帮助我们更好的理解差异。
市面上有一些Diff & Merge工具[2][3],可以通过git config
命令配置所选择的工具(详细说明请参考工具),在冲突发生时,可以通过简单的输入git mergetool
来调用。举个例子,我在自己的Mac上使用Kaleidoscope:
在清理完文件后(无论是通过文本编辑器、Git桌面GUI,还是使用Merge Tool),可以像提交其他更改一样提交文件。输入git add <filename>
,通知git冲突已经解决。
当解决了所有合并冲突并添加到暂存区(Staging Area)后,只需创建一个常规提交,这就完事儿了。
Don’t panic!
如你所见,合并冲突这件事没有什么需要担心的,当然也没有理由恐慌。一旦了解了为什么发生冲突,就可以决定是撤消更改还是解决冲突。记住,并不会产生什么破坏性后果,即使在解决冲突时意识到自己犯了错,仍然可以撤销,只需要回滚到犯错之前的提交,然后重新开始。
如果想更深入了解高级Git工具,可以免费查看“Advanced Git Kit[3]”: 这是关于分支策略、交互式Rebase、Reflog、子模块等主题的短视频集合。
References:
[1] Merge Conflicts: What They Are and How to Deal with Them: https://css-tricks.com/merge-conflicts-what-they-are-and-how-to-deal-with-them/
[2] Diff tools for Mac: https://www.git-tower.com/blog/diff-tools-mac/
[3] Diff tools for Windows: https://www.git-tower.com/blog/diff-tools-windows/
你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind
– END –
原文始发于微信公众号(DeepNoMind):Git进阶系列 | 4. 合并冲突
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/67583.html