(重要!)Git使用入门,使用原理解读及如何在GitLab、GitHub或者Stash上管理项目(三)

上一篇讲了remote相关,让大家基本了解了一下远端库与本地库之间的联系。目前我认为还剩下的容易造成理解混乱的是merge命令以及merge动作的应用场景,下面详述。

首先先给大家解释merge本身的一些内容,再结合一些场景帮大家从混乱的理解中找到思路,进而完全理解Merge Request的意思并掌握这项技能。

merge译成中文是合并,顾名思义,git merge命令时用来合并的,而合并的对象就是branch(分支)。下面我举个简单的应用场景(只在本地Repository中)来说明:本地库中有两个分支testBranch1和testBranch2。目前两个分支中的文件内容相同,都只有一个fileA.txt文件,而且fileA.txt的内容只有一行文字:HelloWorld!

如果你目前处于testBranch1,并且修改了fileA.txt文件在第二行增加了一句:Hello!

此时你的fileA.txt形如:

HelloWorld!

Hello!

不仅如此,你还新建了另一个空文件fileB.txt,并且把所有的修改commit进来。

然后checkout到testBranch2上,此时testBranch2上应该只有一个fileA.txt文件而且内容只有一行HelloWorld! 此时你又修改了fileA.txt在第二行增加了一句HaHa! ,并且把所有的修改都commit进来。

此时你的fileA.txt形如:

HelloWorld!

HaHa!

现在可以想象,testBranch1和testBranch2两个分支分别管理着两套不同版本的内容了。前者有两个文件,后者只有一个文件,而且名字相同的文件内容也有所差别。好了git merge命令马上要出场了,下面请特别注意小编介绍的两个场景:

场景1:

git checkout testBranch1 (即切换到testBranch1分支上),执行git merge testBranch2命令。这样代表:站在testBranch1分支上,把testBranch2分支上的内容融合到testBranch1分支上来

这样git会尝试把testBranch2中的内容与testBranch1融合,而这样是不会改变testBranch2分支上的内容的,只会改变testBranch1上的内容。所以此后testBranch1上有两个文件(fileA.txt和fileB.txt),而testBranch2上依然只有1个文件(filtA.txt)

场景2:

git checkout testBranch2 (即切换到testBranch2分支上),执行git merge testBranch1 命令。这样代表站在testBranch2分支上,把testBranch1分支上的内容融合到testBranch2分支上来

这样git会尝试把testBranch1中的内容与testBranch2融合,而这样是不会改变testBranch1分支上的内容的,只会改变testBranch2上的内容。所以此后testBranch1上有两个文件(fileA.txt和fileB.txt),而testBranch2上也有了2个文件(fileA.txt和fileB.txt)

场景1和场景2在整体上的变化大家明白以后应该就能理解merge命令的含义了吧?下面说一下另一个细节

相信大家注意到,如果第一个分支的fileA.txt和第二个分支的fileA.txt进行融合的话,是有可能产生歧义的。前者的第二行希望是Hello!,后者的第二行希望是HaHa! 那么最终结果到底听谁的呢?这种情况下Git就“有可能产生冲突”。那么在merge 过程中产生冲突是怎样的效果呢?此时你的fileA.txt可能会呈现类似以下的中间状态(此时以场景1的情况为例):

HelloWorld!

>>>>>>>>>

Hello!

=========

Haha!

<<<<<<<<<

类似这样的状态代表Git说:我糊涂了。就需要我们人工来解决这样的冲突。此时我们可以打开fileA.txt文件,发现内容可能如上所示。解决时我们会想:Hello!是我在操作testBranch1时想加的话,HaHa!是我在操作testBranch2是想加的话。两个我都想保存下来,那稍微编辑一下就想搞成如下形式:

HelloWorld!

Hello!

HaHa!

这样解决冲突(即人为编辑)完成后我们保存并关闭文件。

注意!此时我们仍然处于merge的“过程中”,要想完成merge必须告诉Git:刚才冲突的文件就按照我刚才保存的这样解决! 怎么告诉Git呢?就是git add fileA.txt然后git commit -m “解决fileA文件的冲突问题” 两个命令。说白了就是再把最新的fileA.txt文件加入Git的管理。

这些都做完之后,我们就已经渡过了merge过程回家包饺子了。

这里需要理解一个Git的底层原理,这里称其为原理111:在将testBranch2分支merge到testBranch1分支中时,我们像上面那样解决fileA.txt文件的冲突。这样Git就“知道了”上面这个冲突的解决办法,即用形如:

HelloWorld!

Hello!

HaHa!

的内容来替换冲突文件中的内容(因为这是刚才主人决定的)。那么如果此后再将testBranch1分支merge到testBranch2分支中时,我们就不必要再手动解决冲突了,因为Git已经知道该怎么做了。

这个原理会在后面的remote中得到应用,所以希望读者在此能够理解到位。

好了分割线=====================================================================================================================

下面就来讲解一下什么是Merge Request以及怎么进行合理的Merge Request

举一个比较简单的场景:

你们公司的服务器是Stash,上面有个正在开发的项目:ComRepository。这个项目有三个分支:master,worker1,worker2。那么如果把这个项目clone下来之后,本地也会有三个分支:master, worker1, worker2。现在心里要清楚哦,如小编第一篇文章所说,你所知道的是有6个分支的哦,服务器上3个,你本地3个。而对于公司来说,他们不在乎每个员工本地的分支是怎样,他们只在乎服务器上的master分支是否运转正常。因为服务器上的master分支有可能就是公司发表项目时用的分支,所以这个分支上的代码至关重要!

此时公司要求你就在worker1分支上开发吧!那么你的开发流程是什么呢?总之最终目的是要让服务器上的master分支有你开发好的代码。

为了方便,后面依然把本地分支带上后缀(L),如worker1(L)。

一种思路:

在worker1(L)分支上开发,然后checkout到master(L)上,将worker1(L)分支merge到master(L)上来,然后将master(L)的新代码push到服务器的master上去。

这种思路是不该推荐的,如果我是老大,我是不会给你分配master分支的push权限的。因为这样太危险了,master分支是公司至关重要的分支,岂能让你说push就push?这样会让公司的master上的代码时刻处于危险之中。

第二种思路(重要!!!)

就是Merge Request的思路。我们每个开发人员都没有master分支的push权限,但是有pull权限。即只能看,不能写。但是我们有其它分支(如worker1和worker2)的pull和push权限,反正这两个分支也不是太重要的分支,开发者爱怎么糟蹋怎么糟蹋。

那么怎么才能让服务器上的master分支得到更新呢?就是在服务器上进行merge动作,即将服务器上的worker1或者worker2分支上的内容merge到master分支上。这个过程就是Merge Request!所以服务器上的merge动作不是靠你本地git merge命令来完成的,因为你只能操作你本地的分支,服务器上的分支你八竿子打不着,怎么可能轻易去“命令它”?所以这个merge动作基本上是在你们服务器的网页上进行的。比如:你在公司服务器的网站上,发起一个Merge Request,请求把服务器上的worker1分支merge到master分支上去,请求发起要添加一些审核人物,譬如你的老板你的同事。当他们接收到这个Merge Request并同意后,可能会有个“同意”之类的按钮,点击之后就会在服务器上把worker1分支merge到master中。这样做就有效地保护了master分支的安全性。

服务器上的worker1分支的更新就是靠你在本地worker1(L)上更新后push上去的。所以简单的流程就是你早上来上班了,在worker1(L)分支上开发了一天,然后把工作内容都push到服务器的worker1分支上去,再发起一个Merge Request请求把服务器上的worker1分支merge到master上去,然后下班。

分割线==========================================================================================================================

以上就是结合remote和branch来讲解的Merge Request。读者了解之后,可以学习一下下面的非常重要!!!的内容:

试想一下:如果你请求worker1往master上merge,我请求worker2也往master上merge。那么久而久之,我们有可能都改了同一个文件,就可能会产生冲突。那样的话master分支上岂不是乱七八糟了?那么怎么才能让master上的分支一直正确,不产生冲突呢!!!

下面我先说下流程:比如你是在worker1(L)分支上的开发者,做完了一天的工作,先不要提Merge Request,而是先checkout到master(L)上,pull一下,把服务器上master的代码拉下来,使本地的master(L)是最新的master代码,然后checkout回worker1(L)分支,将master(L)分支merge到worker1(L)上,这时候就有可能发生冲突了,因为可能在你下班之前,worker2分支的同事已经提交了代码并且更新了master,而你们恰巧修改了同一个文件。这时候冲突了不要紧,因为冲突是发生在你本地的,你只要在本地把冲突解决了,然后push到worker1分支上去,再提Merge Request,就不会使服务器上的master产生代码冲突了。

原因相信聪明的你已经明白,就是上面提到的原理111 。因为你在本地解决冲突的时候,Git就已经知道产生冲突以后该怎么做了,而你又把这些脚本push到了服务器的worker1分支上,那么服务器的worker1分支在往master分支合并的时候自然就知道该怎么做了。怎么样,Git强大吧?

顺便再建议一下,当你早上来上班时,尽量也checkout到master(L),pull一下,再checkout回worker1(L),把master(L)分支的内容merge过来,完成之后再进行开发。这样就是尽量保持在昨晚之后的最新的代码上进行开发,以减少产生冲突的可能性嘛~
————————————————————————————————————————

流程整理:

本地切换到master,从远程master分支pull——>本地切换到自己的开发分支dev,将本地master代码merge过来——>本地dev分支更新——>本地切换到master,将远程master代码pull下来,使本地master最新——>本地切换回dev分支,将master代码merge到dev上,如果有冲突,手动解决——>将本地dev分支代码push到远程dev分支——>在服务器网页上发起merge request请求,把远程dev分支merge到master上

本地没有分支的情况下,从远程master拉取代码、在本地新建分支并建立追踪关系的两种方式
1)从远程仓库克隆时,Git会自动创建本地的master分支与远程的master分支对应起来,并形成追踪关系
2)利用git fetch origin master取回远程master分支代码,之后利用 git checkout -b master origin/master新建本地master分支来与远程master建立追踪关系。
————————————————————————————————————————

下一篇就开始讲解一些深入的原理知识,同样是以一种比较通俗易懂的角度~Git原理杂谈之pull/push原理
————————————————
版权声明:本文为CSDN博主「小轩腾空」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiaoxuantengkong/article/details/45345867

发布了34 篇原创文章 · 获赞 1 · 访问量 1817

猜你喜欢

转载自blog.csdn.net/weixin_44761910/article/details/105041009