对于学习编程的同志来说,学习Git是必不可少的一项技术,如果你是第一次观看我的文章,欢迎关注我的频道,我会分享更多有趣的知识。
场景一:备份
小明备份的模块快要完成了,就在即将Release之前的一瞬间,电脑突然蓝屏,硬盘光荣牺牲,几个月来的努力付之东流。
场景二:代码还原
这个项目中需要一个很复杂的功能,老王摸索了一个星期终于有眉目了,可是这被改的面目全非的代码已经回不去从前了。
场景三:协同开发
类似于坚果云,但是比坚果云更好用。
场景四:代码追责
项目经理带着一群程序员做开发,可是某一天出了BUG,但是没有人愿意承认,这时候找出这个写出BUG的人至关重要。
在开始谈论版本控制器的方式之前,我们可以看一个小故事。
引用于:Git的诞生 - 廖雪峰的官方网站 (liaoxuefeng.com)
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码。
在那时候,实际上已经出现了一些版本控制系统如CVS、SVN这些版本控制工具,但是Linus认为其并不好用,因为其是集中式版本控制系统,打个比方,集中式版本控制工具就像是去图书馆借书来做笔记,做完笔记后放回去。虽然有一些商用的版本控制系统比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。
不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。
安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。
Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。
Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。
历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。
集中式版本控制工具
集中式版本控制工具,版本库是集中存放在中央服务器的,team里每个人work时从中央服务器下载代码,这个过程必须联网,个人修改后然后提交到中央版本库。所以,这和去百度网盘写笔记没啥两样。例如SVN和CVS。
分布式版本控制工具
分布式版本控制工具没有“中央服务器”,每个人的电脑就是一个完整的版本库,这样工作的时候,无需联网,多人协作只需要各自的修改推送给对方,就能互相看到修改内容了。例如Git。
本教程的git命令例子都是在Git Bash中演示的,会用到一些基本的Linux指令,这个如果不熟悉请移步Linux笔记查看。
git config user.name "名字"
git config user.email "邮箱"
git config --global user.name
git config --global user.email
要使用Git对我们的代码进行版本控制,首先需要获得本地仓库。创建仓库的过程分为以下几个步骤:
隐藏
的.git目录Git工作目录下对于文件的修改会存在几个状态,这些修改的状态会随着我们执行Git的命令而发生变化。
如果需要由工作区上传至暂存区,那么可以用git add
。
如果需要由暂存区上传至本地仓库,可以用git commit
。
常用指令
指令 功能 git log 参数 查看提交日志 git add 单个文件名 | 通配符 添加一个文件或多个文件的修改到暂存区 git commit -m “注释内容” 提交暂存区内容到本地仓库的当前分支 git status 查看当前修改的状态 git reset --hard commitID 版本回退,其中commitID可以在log里面查看 git reflog 查看删除 git reflog 可以看到已经删除的提交记录 git log参数
参数 功能 –all 显示所有分支 –pretty=oneline 将提交信息显示为一行 –abbrev-commit 使得输出的commitld更简短 –graph 以图的形式显示 如果想让仓库的某些文件不用git替我们管理,可以创建
.gitignore
文件,然后用vim编辑器打开添加需要忽略的文件名即可。
几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上来进行重大的bug修改,开发新的功能,以免影响开发主线。
分支命令
命令 功能 git branch 查看本地分支 git branch 分支名 创建本地分支 git checkout 分支名 切换分支 git checkout -b 分支名 创建并且切换到分支 git merge 分支名 一个分支的提交可以合并到另外一个分支 git branch -d 分支名 删除分支时,需要做各种检查 git branch -D 分支名 不做任何检查,强制删除
当两个分支上对文件的修改可能会存在冲突,例如同时修改了同一个文件的同一行,这时就需要手动解决冲突,解决冲突步骤如下:
几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开进行重大的BUG修改,开发新的功能,以免影响开发主线。
在开发中,一般有如下分支使用远程和流程:
master(生产)分支
线上分支、主分支、中小规模项目作为线上运行的应用对应的分支。
develop(开发)分支
是从master创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线要求,都可以在此版本进行开发,阶段开发完成后,需要合并到master分支,准备上线。
feature/xxxx分支
从develop创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完成后合并到develop分支。
hotfix/xxxx分支
从master派生的分支,一般作为线上Bug修复使用,修复完成后需要合并到master、test、develop分支。
还有一些其他分支,在此不再详述,例如test分支(用于代码测试)、pre(预上线分支)等等。
前面我们已经知道Git中存在两种类型的仓库,即本地仓库和远程仓库。那么我们如何搭建Git远程仓库呢?我们可以借助互联网上提供的一些代码托管服务来实现,其中比较常用的有GitHub、码云、GitLab等
gitHub:是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名gitHub。
Gitee(码云):是国内的一个代码托管平台,由于服务器在国内,所以相比于GitHub,码云速度更快。
GitLab:是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务,一般用于企业、学校等内部网络搭建git私服。
学过Linux的都知道,SSH可以用于远程控制。码云基于SSH进行远程传输,所以配置好公钥后,大家都可以利用这个公钥互相传输东西。
生成SSH公钥
ssh-keygen -t rsa
不断回车,如果公钥已经存在,则自动覆盖。
获取公钥
cat ~/.ssh/id_rsa.pub
获取好后,如果想连接码云端的仓库,只需按下图所示:
此时如果想验证是否连接码云成功,可以使用ssh -T [email protected]
指令,如果弹出确认框,输入yes
即可。
这个时候想要把本地仓库和远程仓库绑定,只需输入下面的指令:
git remote add
远程仓库名,通常为origin
仓库SSH地址
如果想要查看绑定了那些远程仓库,只需:
git remote
绑定完成后,我们将本地仓库推送到远程仓库,只需:
git push -f --set-upstream
远程仓库名
本地分支名:远程分支名如果远程分支名和本地分支名相同,则可以只写本地分支,其中-f表示强制覆盖,–set-upstream用于推送到远程仓库的同时并且建立和远端分支的关联关系。
如果想要查看本地仓库和远程仓库分支的对应关系,可以使用:
git branch -vv
第一次推得时候如果建立起分支的关系的话,后面则无需写那么长,只需写:
git push
如果有一个远程仓库,我们可以直接clone到本地。克隆的命令可用:
git clone
仓库路径
本地目录
其中本地目录可省略,会自动生成一个目录
远程分支可以看成是本地分支,我们也可以进行merge操作,只是需要把远程仓库中最新的更新下载到本地,再进行操作。
如果只是抓取,那么其作用是把仓库中的更新都抓取到本地,不会进行合并,并且如果不指定远端名称和分支名,则抓取所有的分支,命令如下:
git fetch
远程仓库名
分支名
如果是拉取,那么会将远端仓库的修改拉到本地后自动进行合并,相当于fetch+merge,而且如果不指定远端名称和分支名,则抓取所有并更新当前分支。
在一段时间,A、B用户修改了同一个文件,且修改了同一行位置的代码,此时会发生合并冲突。
A用户在本地修改代码后优先推送到远程仓库,此时B用户在本地修订代码,提交到本地仓库后,也需要到远程仓库,此时B用户晚于A用户,故需要先拉取远程仓库的提交,经过合并后才能推送到远程仓库分支
,如下图所示:
在B用户拉取代码时,因为A、B用户同一段时间修改了同一个文件的相同位置代码,故会发生合并冲突。
远程分支也是分支,所以合并时冲突的解决方式也和解决本地分支冲突相同。