目录
- 前言
- Git 概述
- 什么是版本控制?
- 为什么需要版本控制?
- 版本控制工具
- 集中式
- 分布式
- Git 工作机制
- Git安装
- Git 常用命令(部分)
- 初始化本地库
- 设置用户签名
- 初始化本地库
- 查看本地库状态
- ***工作区代码编写
- ***添加暂存区
- 撤销工作区的修改
- ***提交本地库
- ***工作区修改代码
- 历史版本控制
- 版本穿梭
- 底层原理
- Git 分支操作
- 什么是分支?
- 分支的好处
- 分支常用操作
- 查看分支
- 创建分支
- 修改,切换,合并分支
- 分支的冲突合并
- 底层原理
- Git 配合远程库(可团队协作)
- 什么是远程库Remote
- GitHub 操作
- 远程仓库基本操作命令
- 创建远程仓库别名
- 推送本地分支到远程仓库
- 克隆远程仓库到本地
- 团队内部协作
- 邀请加入团队
- 拉取远程库内容
- 跨团队协作
- 配置SSH 免密登录
前言
去年11月去实习,进了公司,leader让我先看看一些同事写的相关业务代码,OK,我紧接着就用公司内部的即时通讯软件向有关人员申请了代码查看权限并打了声招呼;
很快我拿到了权限,问题来了,我想直接co里,或者就在网页看看得了,同事路过看不下去了,教了我用git给他pull到本地来…
其实在公司中工作,都是集体干活,分工明确,我们把自己的项目部分完成好,然后通过git这种代码版本控制工具进行管理,比如上传到公司内部的代码库等,方便自己管理和修补自己代码的部分,也方便同事之间review项目的整体代码,找出缺失的部分或者需要修改的部分;
曾经看到过一个段子,一个应届生秋招去了公司,第一天由于被leader发现不会用git,第二天就被开了…缺失,可能学校不会教我们Git这门课程,但是身为一个专业的开发人员,这个相当于是基本的工具,我们最起码要做到对Git能够了解和简单使用;
Git 概述
Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。
Git 易于学习,占地面积小,性能极快。 它具有廉价的本地库,方便的暂存区域和多个工作流分支(统一的远程库)等特性。其性能优于 Subversion、CVS、Perforce 和 ClearCase 等版本控制工具。
为啥学Git? 因为Git开源,免费,而且适配linux等(就是人家团队搞出来的工具)
什么是版本控制?
版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。
版本控制其实最重要的是可以记录文件修改历史记录,从而让用户能够查看历史版本, 方便版本切换。
eg:
上面这个段子就是某个学生手动进行的版本控制,每次都需要进行手动copy,再修改,再存储,重命名+版本号,显然很麻烦;
为什么需要版本控制?
- 个人开发过渡到团队协作
假设小红人为A,小蓝人为B:
假设A和B同时对同一个代码进行优化,A在第二行添加了222,B在第四行添加了444,他们的代码优化都是有效的想被保存的;
如果没有用Git,A和B自己进行修改,然后保存,且源文件名字不变呢?加入A改的快,A改好了存好了,B这时候改完了,也需要保存,把刚才A改好的文件就覆盖了,那么代码第二行的优化就不见了。。显然是不理想状况;
他俩可以用Git进行版本管理,Git的机制会保证最终库中能达到序号3所示的理想结果;
版本控制工具
集中式
CVS、SVN(Subversion)、VSS……
集中化的版本控制系统诸如 CVS、SVN 等,都有一个单一的集中管理的服务器,保存 所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或 者提交更新;
好处:
每个人都可以在一定程度上看到项目中的其他人正在做些什么。
而管理员也可以轻松掌控每个开发者的权限
管理一个集中化的版本控制系统,要远比在各个客户端上维护本地数据库来得轻松容易。
缺点: 中央服务器的单点故障。如果服务器宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作
分布式
Git、Mercurial、Bazaar、Darcs……
像 Git 这种分布式版本控制工具,客户端提取的不是最新版本的文件快照,而是把代码仓库完整地镜像下来(本地库)
任何一处协同工作用的文件发生故障,事后都可以用 其他客户端的本地仓库进行恢复;(因为每个客户端的每一次文件提取操作,实际上都是一次 对整个文件仓库的完整备份。)
解决了集中式版本控制系统的缺陷:
- 服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)
- 每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全,宕机也能从别的恢复)
Git 工作机制
工作大致流程框架如下:
我们团队的每个人在自己的主机(工作区)进行代码编写,临时离开暂时保存可以使用git add添加暂存区(还是在我们主机内之后我们自己能看到),如果该版本代码已经写好,我们把它进一步git commit提交到本地库存放,本地库里面可能存放了历史版本,我们可以对其进行合并覆盖或者回滚等操作;
等最后经确认代码没问题了,我们再把最终的源码上传到整体项目远程库(github,gitee或者公司积极搭建的gitlab中);
核心图如下:
Git安装
进入以下链接选择对应版本
https://git-scm.com/
安装好后,右键任意位置,在某个路径右键菜单里选择 Git Bash Here 即可打开 该路径下的 Git Bash 命令行终端。
当然也可用linux命令进入指定路径,他俩是一家的;
Git 常用命令(部分)
初始化本地库
默认初始化分支(目录)为:master,关于分支的概念,后面详细介绍;
设置用户签名
git config --global user.name 用户名
git config --global user.email 邮箱
说明:
签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。Git 首次安装必须设置一下用户签名,否则无法提交代码。
初始化本地库
在git项目目录中右键启动git bash,输入如下命令:
git init
查看本地库状态
git status
首次查看(当前工作区没任何文件):
***工作区代码编写
新增文件(hello.txt)
和linux操作一模一样:
**再次查看状态 **
这里会发现,怎么跟刚才没文件的效果差不多?还是No commits,不过注意到刚才加进来的hello.txt出现了,还是红色,标注未被追踪!
原因是刚刚只是我们在工作区进行的临时代码编写,只是一份临时文件,说不定我们下一秒就不要了,所以我们还没有进行git add添加追踪到暂存区;
***添加暂存区
- 将工作区的文件添加到暂存区
git add 文件名
这个小警告可以忽视,因为linux中的换行符于win中的换行符不容,系统帮我们自动替换了;
**再次查看状态 **
显示new file hello.txt,并且变绿色,代表追踪上了,代码进入暂存区了,现在我们工作区的文件被删了也不怕了,暂存区中有一份了!
撤销工作区的修改
加入我们将hello.txt添加暂存区之后,从win中删除,会发生什么?
则:
git rm/add hello.txt 代表删除该文件在git中的缓存
git restore hello.txt 代表,恢复工作区的改变,也就是说恢复工作区中误删的文件hello.txt
文件回来了而且恢复到上次被git add追踪的状态了;
***提交本地库
git commit -m "日志信息" 文件名
日志信息类似于注释;
(刚才的hello.txt提交了,工作区没啥新改动文件或者说可以commit的文件了)
***工作区修改代码
再次查看状态,git检测到工作区有文件被修改
我们再次提交入暂存区,变绿:
进一步commit到本地库:
历史版本控制
git reflog -- 查看版本信息(已提交过的本地库中的某文件的版本信息)
git log -- 查看版本详细信息
这里就体现了本地库中:多版本的概念!(工作区win中还是只有一份文件哦)
ref是引用的意思,这里用作简单信息;
版本穿梭
git reset --hard 版本号(ref简单信息的前几位版本号就行)
可以看到,刚刚修改的hello.txt中 第一行的一串1111111 不见了,版本回溯到之前的版本了!
更好的体现了git可以帮我们管理某份代码(hello.txt)的历史版本,还支持回溯功能(不过前提是你得先对他commit到本地库中过)
底层原理
Git某一分支下的 切换版本,底层其实是移动的是某一分支(eg:master)下的版本指针,具体原理如下图所示。
Git 分支操作
什么是分支?
在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独分支。
使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时 候,不会影响主线分支的运行。(eg旧版本上线使用的时候,开发人员在另一个dev分支改造新版本)
对于初学者而言,分支可以简单理解为副本,一个分支就是 一个单独的副本。(分支底层其实也是指针的引用 Head指针指向的引用)
实际应用如下图:
hot-fix为热修复分支,也就是补丁版本,feature-blue为蓝色模块,feature-game为游戏模块;
在保证master主分支的线上版本运行的状态下,对其他版本进行开发设计,在一定的时间点,合并分支,相当于为这个线上版本进行了修复或者引入了新的模块功能;
分支的好处
同时并行推进多个功能开发,提高开发效率。(高效)
各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可;(解耦)
分支常用操作
查看分支
git branch -v
创建分支
git branch 分支名
这里以创建hot-fix热修复分支为例
修改,切换,合并分支
修改+切换
git checkout 分支名 -- 切换分支
首先各分支分别修改并add + commit到本地库hello.txt文件
master分支下的hello.txt:
hot-fix分支下的hello.txt:
之后经过多次切换分支,发现当Head指针指向哪个分支的时候,他们的hello.txt不冲突,都看得到自己的内容,而却本地工作区的hello.txt内容随Head指向分支而变化!这就自动化的帮我们管理了不同的分支(副本),使其相互不受影响!
合并
git merge 分支名 -- 在哪个分支上运行这个命令,就是把指定名字的分支,合并到当前分支来
我们切换回master分支,进行hot-fix分支的合并,模拟一个线上产品打补丁的过程:
可以看到,hot-fix分支的txt合并到了master分支,并且git status发现git合并分支的时候已经自动帮我们进行了add+commit!(别忘记,不想要了我们可以回溯哦 git reflog+reset)
分支的冲突合并
产生冲突
有时候进行分支合并时,会产生冲突,举例如下:
修改master 和 hot-fix的txt文件如下图,并commit:
可以看到,我们master里给最后一行行加了句 test conflic; hot-fix分支给第一行加了这句; 接下来合并;
发现产生冲突,并且当前分支的括号内出现MERGING;
产生冲突的原因
合并分支时,两个分支在同一个文件的同一个位置有两套完全不同的修改。Git 无法替我们决定使用哪一个。必须人为决定新代码内容。 查看状态(检测到有文件有两处修改)
简单来说,合并得两个分支,某行代码产生冲突了,那么就需要认为的选择留哪个分支的冲突代码了!
解决冲突
- 编辑有冲突的文件,删除特殊符号,人为决定要使用的内容
特殊符号:<<<<<<< HEAD 当前分支的代码 ======= 合并过来的代码 >>>>>>> hot-fix
编辑完成:
假设保留master的改动:
之后正常add;添加入暂存区;
之后执行提交;注意,解决冲突合并的commit比较特殊,不能带文件名!!
之后会发现MERGING消失,冲突处理完成!
底层原理
Git 配合远程库(可团队协作)
什么是远程库Remote
我们上述讲的什么工作区add到暂存区再commit到本地库保存当前版本,或者说本地库中多分支的合并等操作,这一切的一切都是在我们主机(电脑)上操作和保存的,这显然是不行的,如果多人合作,你写的代码人家肯定也要看到,人家如果改你的到吗,最新的代码也要能被你拉取到,这就需要多主机与一个远程共享库配合操作了;
企业中一般会搭建自己的代码库配合git进行代码的管理;
如果是开源项目等,那就用github或者gitee这种直接公开沧湖进行管理就行;
GitHub 操作
首先我们注册登录自己的GitHub,创建一个公开的仓库,名字叫Demo;
远程仓库基本操作命令
创建远程仓库别名
git remote -v -- 查看当前所有远程地址别名
git remote add 别名 远程地址
注意,这里的远程地址如下图, 旁边的SSH用于免密登录我们后续再讲;
Git实操:
推送本地分支到远程仓库
git push 远程仓库别名(HTTPS or SSH) 分支名 o
我们提交之前测试用的master分支到github新建的仓库,提示认证,可以选择通过浏览器的cookie认证,
认证和提交成功以后,我们刷新下仓库,会看到提交的内容(提交其他版本,比如hot-fix同理):
你会发现,提交时间是当时commit到本地库的时间,并不是刚刚push到远程github的时间,而且push上去的注释这些,都和本地库当时commit的一致;
git github是一个公司发明的; github可以看做是git的官方远程库!
克隆远程仓库到本地
git clone 远程地址
为了区分效果,我们在另一个工作区tmp进行clone演示
可以看到整个远程仓库Demo被clone下来了
小结:
clone 会做如下操作。1、拉取代码。2、初始化本地仓库。3、创建别名
团队内部协作
邀请加入团队
1.选择邀请合作者
2.填入想要合作的人
3.设置好以后,复 制 地 址 并 通 过 微 信 钉 钉 邮箱 等 通讯工具 方 式 发 送 给 该 用 户 , 复 制 内 容 如 下:
4.受邀人登录 atguigulinghuchong 这个账号,在地址栏中直接粘贴上去收到邀请的链接,点击接受邀请。
5.成功之后可以在 atguigulinghuchong 这个账号上看到 git-Test 的远程仓库
且受邀人有权限可以修改仓库中的代码内容,并push到远程仓库;
受邀人:(可以clone到他的工作区修改,在push回远程库,也可以直接在远程库中修改…)
拉取远程库内容
git pull 远程库地址别名 远程分支名
作用,将仓库中的指定分支最新内容pulk拉取下来,并merge与本地对应分支直接合并;
跨团队协作
同时,除了团队协作外,也可以跨团队协作,比如外包之类的,让别的公司也能修改,不过他的更新远程库需要request Pull请求,我们库中的管理者审核代码并通过以后(可以检查代码,或者使用github内置的即时聊天窗口交流),才会成功的更新远程库的代码;
配置SSH 免密登录
刚才我们可以看到远程仓库中除了HTTPS,还有一个 SSH 的地址,因此我们也可以使用 SSH 进行某个主机对某个授权用户的仓库访问,不需要浏览器验证github账户了;
win/用户目录下的.ssh中寻找配置好的ssh公钥:
复制给仓库的主人,让其许可这个公钥的主机访问仓库:
本人配置后,ssh链接如下:
之后,进行pull和push的时候,就可以使用HTTPS右边的SSH免密链接,来进行操作了;
同时,各种编译器eg: IDEA VSCODE 也都有git工具,让我们在编译期内就能进行代码管理,不需要命令行,那就更方便了!