[工具] 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