冲突解决


冲突问题
可是人生哪有处处都如意的时候呢,代码也是如此。如果A和B都同时修改了同一个文件会发生什么呢,此时就会发生冲突。

比如张三修改了 A.java文件上传到了中央服务器,然后李四在本地也修改了 A.java文件,李四想提交文件时,会提示因为冲突而无法提交。系统要求你先把代码拉下来,合并了A.java的冲突(这个合并过程,其实有时候git会自动合并,但是复杂的合并git做不了,所以就要求李四自己去合并冲突),然后李四才能提交上去。。。

当然,你工作电脑上提交,然后 自己私人笔记本上又修改了同一个文件,这和上面是同样的意思,只是 我们用张三李四来方便表达。

所以为了避免潜在冲突一个好习惯就是 你在修改你的代码之前,先git pull一下,把服务器的最新代码拉下来,这是一个好习惯。

因此我们开发时,有时候早晨来了第一件事情,就是先把代码git pull一下,进行更新。这是个好的开发习惯。避免你写了很多代码,你同事也写了很多代码,然后冲突了,你们俩合并的时候,比较浪费时间。

我现在就实际做一个冲突的demo,演示冲突是怎么发生的,又怎么解决。其实都很好解决。。

我在自己的mac电脑上修改了 FixedThreadPool.java文件,然后 在mac电脑上 操作了 add,commit,push操作,提交到了远程服务器上。

而同时,我在自己的工作电脑上, 也对 FixedThreadPool.java文件 进行了修改。然后我在自己的工作电脑上, 执行了add,commit操作,现在我要提交了,我执行了 push操作,看看会发生什么。

图片名称:git_push_error_because_confilt.png
git_push_error_because_confilt.png-63.2kB

此时再看看对方 termial提示了什么。输出了一大串内容,前面的内容不用关心。
我们只看最后一段主要内容。

To [email protected]:yaowen369/ConcurrentDemo.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to ‘[email protected]:yaowen369/ConcurrentDemo.git’
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push --help’ for details.
翻译其中的主要内容:

! [拒绝] master -> master (fetch first)
错误:向’[email protected]:yaowen369/ConcurrentDemo.git’执行 push时,发生了某些错误。
提示:更新之所以被拒绝是因为 远程分支包含了你本地没有的内容,这通常是因为 另一个库推送了同样的文件(ref是索引的意思,可以翻译成文件)。你可以在推送之前先合并这些远程的变化(比如,试试 git pull)。

你可以看看 git push --help中的 Note about fast-forwards了解更多的细节。
其实在命令行中,help是很有用的,可以提示很多有用的帮助信息,不过有些termial要求直接 命令后面输入 help就好了,有些要求输入 -help,有些要求输入 --help,或者有些直接输入 -h/–h也行,但是我们始终要有这个意识,因为太多东西不用记忆,有个大概的印象就好。(计算机常识)

看到这些提示内容,即使你第一次碰到这个问题,你下一步准备怎么做?人家已经给你提示了啊。直接 git pull啊。

Notice:在你输入 git pull时,有时候termial会要求你输入密码,有时候不会,但是 很快的,termial就会完全的跳转到一个新的页面,这应该是你第一个碰到这种情况。

图片名称:git_pull_confilit_vi.png
git_pull_confilit_vi.png-35kB

这其实是个vi编辑器,(vim是vi的升级版,因为vim颜色高亮做的比较好,看起来更舒服)。
我们在之前执行 git commit -m "相关提交的log内容"这个命令时, 直接输入 一行提交说明内容,所以没那么复杂,我们就写一句话 说明一下而已(搞那么复杂干啥子)。但是你如果执行 git commit, 不带-m 然后你直接敲击回车,也会进入这个vi页面。(因为你没使用一行的提交说明模式,系统会以为你想长篇大论的去写提交信息呢,所以专门给你准备个编译器,你好好写吧,想写多少,就写多少)

说简单点,vi和你的word,notepad,sublime text没啥区别,包括和你电脑上新建个 文本文档,都是一回事, 都只是一个文本编译器, 但是这个 vi的历史可比后面的那几个历史早太多了,上世纪八十年代,电脑图形化界面还没发明呢,当时电脑操作都是黑乎乎的命令行窗口操作(其实现在window,linux也可以直接黑乎乎的termial操作,只是那么多命令,大家都记不住,有了鼠标和图形化界面,黑乎乎的命令行操作都被忘记了,只剩下程序员使用termial了)。word 等更无从谈起,但是大家很多时候也要 编译文本啊,又没有word等,所以vi就是一个当时环境下的 termial环境操作的 文本编译器,完全 键盘操作,有无数复杂的 快捷键,你使用vi操作,完全不用接触鼠标,所以操作也比较快(当然是在你比较熟悉快捷键的情况下,否则你就尴尬了)。

我们这里呢,不讨论vi。vi的操作是另一个话题。(其实也不是难,而是那么多复杂的快捷键组记忆着比较困难而已)。

我们可以看看 它上面的内容说了什么。

Please enter a commit message to explain why this merge is necessary,

Lines starting with ‘#’ will be ignored
翻译内容:

请输入一些提交内容来解释为什么这次合并是必须的。
#号开头的行都会被忽略(注释的作用)
其实上面那句Merge branch ‘master’ of git.oschina.net:yaowen369/ConcurrentDemo,就是它默认帮你生成的 提交信息。
反正你不用管(因为你要搞定这个,这是另一个学习内容,但是你学习这些完全没必要,虽然也不难。这也是source tree等软件的好处,使用了 source tree等图形化软件,你怎么着也不会碰到vi界面),还记得 怎么退出不?

输入:q, 字符q代表是退出(quit)的意思,不过这个 vi的退出要 一个冒号+q,所以你输入 :q,直接退出就好了。(git有些界面退出也是:q,只是你输入命令操作的时候,git自动帮你前缀一个冒号了,所以给你省事了而已)

你输入 :q,注意左下角。

vi_q.png-60.2kB

vi当中: 开头的都是命令模式,命令模式显示都在左下角。你输入 :q回车后, 左下角出现了这么一行红色的文字。

E37: No write since last change (add ! to override)
你输入:q竟然没用,相关区域提示你,因为这个文件你啥都没改动,所以你要加个!号去覆盖(其实就是强制退出模式)。 然后你直接输入 :q!就好了。(直接输入:号就好了,那行红色的提示就消失了,然后你接着输入q!就好了,你试图用键盘上的delte等按键去删除红色文字没用的)

还要讨论vi的相关内容。但是不讨论用户十有八九又会碰到这个问题,当年我第一次碰到vi问题,连怎么退出都搞不定,急的满头大汗。所以不得不讨论。

终于我们退出了 vi,看看具体提示了什么。。

confilit_after_vi.png-29.1kB

红色方框内的内容不要管,那是因为我第一次在vi中输入命令 时,输错了 :!q,所以vi提示 q命令找不到,我又重新进入输入了 :q!,就ok了。。

我们看重点内容:

Auto-merging java/src/thread_runnable/FixedThreadPool.java

Merge made by the ‘recursive’ strategy.
java/src/thread_runnable/FixedThreadPool.java | 4 +±-
1 file changed, 2 insertions(+), 2 deletions(-)
注意:Auto-merging自动合并了。也就是说, 因为我刚才测试的冲突比较简单,所以 git自动比较合并了。(比如张三修改了文件的第一行,李四修改了文件的最后一行,这种简单的,git就能自动合并,但是张三李四都修改了 文件的第一行,那就只能手动合并了)。

那么此时你使用git status来查看状态,

$ git status .
On branch master
Your branch is ahead of ‘origin/master’ by 2 commits.
(use “git push” to publish your local commits)
nothing to commit, working directory clean
你的工作区很干净,没啥可commit的,但是 注意上面那句话
Your branch is ahead of ‘origin/master’ by 2 commits.
你当前的分支领先 远程分支 两次提交。

为啥是两次,因为本来你就commit了一次,然后 git pull时,又自动合并commit一次,所以就两次了。

不用关心几次,看到重点就对了,你当前的分支领先远程分支。
另外,扯了这么大一段,别忘记了最初咱们的目的是什么,咱们最初的目标就是 推送代码到远程服务器。

所以接下来直接 git push,将 代码直接推送到远程服务器就好了。

这次的冲突因为我制造的比较简单,所以自动合并了,但是有些冲突比较复杂,git无法自动合并,
那么此时就需要你手动合并了。

下面的demo直接借用了网上别人的代码冲突内容 ,我针对输出进行解释。

$ git pull
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
系统提示你,test.txt文件冲突了,自动合并失败了,你需要解决冲突,然后并提交。。

好,我打开test.txt文件,会看到下面的情况。

Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.

Creating a new branch is quick AND simple.

feature1
其中冲突的部分都是用 <<<<<<<,=,>>>>>>>来进行标记了,他们都代表了不同分支(或者远程/本地)不同的内容,你自己看着代码,把<<<<<<<,=,>>>>>>>进行删除,该删除的代码部分也进行删除。

如果是你自己写的代码,你肯定知道该删除那些内容,如果不是你写的代码,比如李四写的,那么你要叫着李四讨论,把你们两个的代码合并掉。李四写的代码你又不了解业务逻辑,你不和他讨论, 就瞎合并,这在多人团队中,是大忌。

因为你可能把李四写的代码给覆盖掉。而程序员基本上写完某个文件就不再关心了,所以李四也不知道你把他的内容覆盖掉了,这肯定会引起问题,如果测试人员能发现业务逻辑不对,那还好,最多被测试人员提个代码臭骂一顿,但如果测试不能发现,那等着线上事故吧。

比如上面的那段冲突,我们合并成如下形式,并进行文件保存。

Creating a new branch is quick and simple.
合并之后,相当于你又重新 修改了文件。
所以在此重新进行提交步骤。。

$ git add readme.txt
$ git commit -m “老子把冲突合并了”
[master 59bc1cb] 老子把冲突合并了
最后再push就好了。。

到了这里我们就理解了平时的提交代码,拉取代码的步骤,以及怎么解决冲突。
我们再来学习一个命令。git log:

git log: 查看之前每次提交的说明信息:

git_log.png-78kB

直接看输出应该一目了然了。每次提交的版本号。作者,时间,提交的信息说明 都直接列出来了。咱们之前在 git commit -m “说明信息”,这里就有用了,否则那么多次提交,谁也没本事都记住啊。

尤其是你注意最上面那个 说明信息:

commit fb095209cc6adf53a98035cc7661d109a2024de9
Merge: 5b90fa3 c63c40b
Author: yaowen [email protected]
Date: Sat Sep 9 11:45:40 2017 +0800

Merge branch 'master' of git.oschina.net:yaowen369/ConcurrentDemo

最上面的是 版本号(就是那一长串奇怪的字符串),git的版本号是一长串字符串,而svn的版本号就是很简单的1,2 ,3, 4阿拉伯数字,简单来讲,因为svn你每次提交拉取时,都是直接与中央服务器交互,而git则是先与版本库(暂存区)交互,多人都使用git来提交代码,他们本地的电脑时间都不一定准确,不能使用1, 2, 3,4作为版本号,因为不能简单的依据时间戳来比较。而svn则可以直接使用服务器时间。

这次提交信息,还很贴心的给你提示了,你这次提交其实是一个 合并冲突操作merge,并且提交的说明信息Merge branch ‘master’ of git.oschina.net:yaowen369/ConcurrentDemo,就是刚才合并时系统帮我们生成的。(因为当时我们在vi界面并没有修改默认的提交说明信息啊)。

注意右下角的冒号, 因为我这个项目提交很多次了,所以log说明比较多,一页显示不完,你还记得怎么上下翻页,怎么退出log提示不?(翻页一般用不到,因为我们一般看提交log也都是看最近的几次说明,不过怎么退出这肯定是要知道额)

猜你喜欢

转载自blog.csdn.net/qq_25004825/article/details/83308314