[工具] Git版本管理(二)(分支)

一、分支

1.git中如何保存版本

在我们以往使用文件来进行版本控制的时候,都是将上一个版本复制一份,然后在其基础上进行修改。

但在git中,git只保存当前版本和上一个版本之间的差异,这样可以节省存储空间, 在生成版本的时候速度也会更快。

 

2.Master主线

如下图所示:

 

 

当只有一条主线Master时,新版本都是在上一个版本的基础上进行修改的,例如Version2在Version1的100个文件基础上,新增了20个文件,并修改了其中10个文件。

也就是说Version2只需要保存新增的20个文件,以及修改的10个文件的修改信息,当我们需要Version2的时候,git再去Version1中拿未修改的90个文件。

同理,Version3、Version4也是如此。

 

3.分支概念

当我们需要已某个版本作为基准,同时开发多个新功能,则可能在该基准版本处产生分支,如下图所示:

 

处理线上系统的紧急BUG:

例如,Version3是已上线的版本, 我们在Version3的基础上开发新功能:

 

Version3突然出现紧急BUG,需要修复,怎么办?我们可以在Version3的基础上新开一个分支,专门用作BUG修复,修复完后合并到主分支:

 

 

 

 而负责新功能开发的分支,可以继续研发新功能,不受影响。等到新功能开发测试完毕后,也可以合并到主分支Master中去。

 

4.创建分支(开发新功能)

1)查询分支信息

git branch

 

 

可以看到,我们目前只有一个master主分支。

2)创建新的分支(开发商城功能)

git branch dev_shop

使用命令创建了一个分支,叫做dev_shop。用于开发新功能,商城。

 

 

"*"号代表我们所处的分支。

3)切换分支

使用命令:

git checkout dev_shop

 

 

可以看到,我们已经切换到了dev_shop分支,我们在这个新分支下编写代码,是不会影响到其他分支的。

通过git log查看一下版本信息:

 

 

 可以看到,我们所处的版本是"修改约饭-->约",但是分支处于dev_shop。而在这个版本处存在两个分支:master和dev_shop。相当于下图所示:

 

如果我们在dev_shop分支上再生成一个版本,则会变成如下:

 

在分支中添加了商城功能后,使用git log查看版本信息:

 

 

5.创建分支(修改BUG)

 1)切换回master分支

git checkout master

2)创建新分支(修改BUG)

git branch bug

查看分支:

git branch

 

 

3)切换到BUG分支

git checkout bug

修改代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
    <ul>
        <li>欧美</li>
        <li>日韩</li>
        <li>港台澳</li>
        <li>直播</li>
        <li></li>
    </ul>
</body>
</html>

将"港台"修改为"港台澳"。并提交生成新的版本。

此时查看git log:

 

 

 此时的分支结构为:

 

6.合并分支

将bug分支合并到master分支中。

1)切换回master分支

git checkout master

2)合并bug分支

git merge bug

 

查看当前的版本信息:

 

 当前的分支结构:

7.删除分支

当Master分支将bug分支合并之后,bug分支就没用了,可以使用命令删除bug分支:

git branch -d bug

删除后,查看当前分支信息:

可以看到bug分支已经被删除。

 

8.继续开发dev_shop

1)从Master切换到dev_shop

git checkout dev_shop

2)继续开发dev_shop,并提交

 

 

9.将dev_shop合并到Master中

1)切换回Master分支

git checkout master

2)合并dev_shop分支

git merge dev_shop

当合并的时候,如果没有冲突(例如都是添加代码),则可以自动合并。

自动合并后会生成一个新的版本:

如果产生了冲突(例如修改了同一行代码),则自动合并失败。

当产生冲突的之后,git会将两个文件所修改的地方全部放在文件中,然后由我们人工进行处理:

 

 我们人工修改为最终版本后,再次进行git add 、 git commit操作,重新提交即可。手工生成的版本信息,由我们自己指定。

 

二、分支总结

1.查看分支

git branch

2.创建分支

git branch 分支名

3.切换分支

git checkout 分支名

4.合并分支

git merge 分支名

注意,假设分支2要合并到分支1中,则需要切换到分支1中执行"git merge 分支2"。

 

三、简单工作流

git中默认有一个master分支,但是不建议我们直接在master分支上去做开发,master分支主要用于保存正式版本(稳定版本)。

我们开发新的功能,都应该去一个单独的分支上去做开发。例如叫dev的分支。如图所示:

 

从图中可以看到,我们的开发都在dev分支上做,而master分支的版本都是稳定版本。

类似于QQ的稳定版和beta版,稳定版在master分支中,beta测试版在dev分支中。

 

以上就是最基本的工作流。

 

四、github

github和git其实没有本质的联系,github只是一个类似于云盘的代码仓库。除了github,还有CSDN、码云等平台也提供类似的功能。

要使用github,需要以下几个步骤:

1)注册一个github账号

2)创建一个仓库

3)将本地代码推送到github仓库

 

1.注册github账号

(略)

2.创建仓库

 

Repository name尽量与项目名一致,方便查找。

Description用于描述项目。

Public表示开源(代码公开),Private表示只有自己能看到。

Initialice this repository with a README,自动创建一个README文件。

Add .gitignore表示创建一个不被git管理的文件夹

Add a license表示我们代码的许可证。

 

3.推送代码到仓库

 

 在我们的项目文件夹中打开git bash窗口,执行命令:

git remote add origin https://github.com/leokale/dbhot.git

origin就是我们要推送的目的仓库的别名。

然后再执行push命令:

git push -u origin master

推送master分支到仓库。

此时会弹出一个用户名密码窗口,用于github验证:

 

输入账号密码通过验证后,可以看到推送成功:

 

此时,我们可以在github中看到仓库里存放着master分支的相关文件:

 

推送dev_shop分支的代码到仓库:

git push -u origin dev_shop

第二次推送,就无需验证github账号密码了。

 

此时,在github仓库中,可以看到多出了一个dev_shop分支。

 

 

4.从仓库拉代码

例如我们在另一台PC上,进入一个根目录(用于存放dbhot项目文件夹)。

 

在该目录打开git bash:

获取仓库的地址:

 

 使用命令拉取代码:

git clone https://github.com/leokale/dbhot.git

 

可以看到该目录下出现dbhot文件夹:

 

进入目录使用git bash即可:

 

5.github总结

1)给远程仓库起别名

git remote add xxxx 远程仓库地址

2)向远程推送代码

git push -u xxxx 分支名

3)克隆全程仓库代码

git clone 远程仓库地址

当克隆代码之后,实际上帮我们执行了git remote add origin 远程仓库地址。所以我们以后推送的时候,可以使用origin就可以了。

 

五、局部代码推送与拉取

例如目前的版本结构如下图所示:

 

当我们要继续在dev_shop分支上去做开发时,发现dev_shop分支的代码不是最新的,因为master分支合并了bug分支和dev_shop分支。所有当前master分支才是最新的。

所以,我们在开发代码之前,首先在本地将master分支合并到dev_shop分支中,让dev_shop分支变为最新代码:

git checkout dev_shop
git merge master

 

 

合并后,dev_shop分支中的代码已经变为最新版,也就是和master分支一样,版本为"Merge branch 'dev_shop' "。

 

1.推送部分代码(在PC-A上的操作)

在dev_shop分支中开发新代码(例如新增一个a1.py文件):

touch a1.py

保存一个版本:

git add a1.py
git commit -m "在PC-A添加了一个新文件a1.py"

推送到仓库:

git push origin dev_shop

此时在仓库的dev_shop分支中可以看到:

 

 

2.拉取部分代码(在PC-B上的操作)

首先,切换到dev_shop分支:

git checkout dev_shop

然后,拉取在PC-A上提交的部分代码(a1.py文件):

git pull origin dev_shop

在a1.py中添加内容:

# a1.py文件

print("HELLO WORLD")

将新的代码推送给仓库:

git add a1.py
git commit -m "在PC-B中修改了a1.py"
git push origin dev_shop

3.pull命令分解

在git中,git pull命令实际上可以拆分为以下两个命令:

git fetch origin dev_shop
git merge origin/def_shop

git fetch的意思是将dev_shop分支从远程仓库(github)拉回本地版本库。由于拉回版本库,可能和本地的dev_shop不一致,所以名字为origin/dev_shop

git merge origin/dev_shop的意思是将原来仓库拉下来的dev_shop(origin/dev_shop)合并到工作区。

当然,merge的时候origin/dev_shop分支和本地的dev_shop可能存在冲突(例如PC-A上开发的代码忘了推送,然后在PC-B上又开发了其他代码并推送到了仓库,再在PC-A上fetch下来,就会不一样),需要我们手工解决冲突。

 

六、查看版本分支结构

1.graph参数

使用git log查看版本结构的时候,可以加上--graph参数:

 

 

 

2.简化模式

git log --graph --pretty=format:"%h %s"

 

%h:hash值(短)

%H:hash值(长)

%s:备注信息

%an:作者

%ae:作者email

%ad:提交时间

其他格式化字符参考:

git log --help

 

七、变基(rebase)

变基:git  rebase。

有以下三种使用场景。

1.合并多个提交记录

当我们反复在不同的地方开发代码时,可能会经常commit,然后push,这样会生成很多提交记录(版本)。这对于我们自己可能是由意义的,但是对于其他协同开发者是没有意义的。

例如,在某个项目中,我们一共有4条提交记录:

 

假设,我们想将v2~v4合并成一个提交:

git rebase -i af57743e74ce9f36a8f142e87cd10599b6a36fc4

后面的ID就是v2这个提交的ID。他会将v2~当前提交这三条提交合并成一个提交。

另一种方式:

git rebase -i HEAD~3

HEAD~3是从当前提交往前数3个提交,合并成一个。

执行上述任意一个命令后,会进入以下画面:

 

我们关注最前面的三行(pick *****),将v3和v4的"pick"修改为"s":

 

表示将v3和v4合并到v2中,:wq保存,进入另外一个画面:

 

修改合并后的commit的描述信息:

 

:wq保存:

 

执行git log查看提交记录:

 

我们可以看到,合并后的commit的时间和v2的时间一致。

 

2.补充

在执行git rebase HEAD~3命令以后,进入的第一个画面:

我们关注的最前面三行,是分别对三个版本的处理方式:

1)pick:表示使用commit,如果3个版本都是pick,则不发生任何改变,还是v2 v3 v4。

2)reword:同pick,使用commit,但是可以修改备注信息。保存后,会进入修改备注的页面。按r指定的版本,一个一个修改备注。

3)squash:标记为s的版本,会向前合并,例如v4标记为s,则会合并到v3中,以此类推。

4)fixup:和squash很像,但不会进入修改备注的界面,也就是说丢弃标记f的版本的备注信息,并合并到前一个版本中。

5)drop:删除指定的版本。

 

注意:在使用rebase合并版本时,最好不要是已经push到仓库的版本,最好是合并好后再push到仓库中。

 

2.将分支的版本合并进master(变成master一条线)

例如,我们目前master有2个版本,分别为m1和m2。

在m1处,创建了分支dev,并且提交了版本d1。

此时的结构如下:

 

我们如果使用git merge命令,则会将其变为:

 

但是我们想将其变得更简洁,例如下图:

使用命令:

git checkout dev  # 切换到dev分支
git rebase master  # 将dev作为base,相当于将master合并进dev
git checkout master  # 切换回master
git merge dev  # 将dev合并到master

执行上述命令后,master和dev分支的版本都是m1<----m2<----d1。如果不需要dev分支,则将其删除即可:git branch -d dev

 

 

3.合并不产生分叉

在《第五节:局部代码推送与拉取》中,我们在PC-A和PC-B上分别开发了代码,PC-A提交在本地版本库,但没有推送到远程仓库。而PC-B的推送到了远程仓库。

当我们在PC-A上pull仓库的代码时,git会帮我们自动进行合并,但可能产生冲突,然后由我们手动解决冲突。

我们知道pull命令可以拆分为:

git fetch origin dev
git merge origin/dev

但是,在这种情况下,一定会产生分叉,因为fetch回来的分支叫做 origin/dev,而本地的叫做dev。

此时,可以使用rebase来代替merge:

git fetch origin dev
git rebase origin/dev

 

4.rebase时解决冲突

当我们在master和dev分支中都对同一个文件的同一行进行了修改,并都提交到了版本库。我们使用rebase将他们合并成一条分支时,会报冲突错误:

 

此时,我们可以按照报错提示,去m3.py中查看冲突:

 

解决冲突:

 

然后执行命令,继续rebase:

git add m3.py  # 处理完冲突后,要使用add加入暂存区或使用rm命令删除
git rebase --continue  # 然后继续执行rebase操作

 

 

666

posted @ 2019-12-29 17:15  风间悠香  阅读(783)  评论(0编辑  收藏  举报