git的使用: 版本控制系统
-
多人协作开发同一个项目 git分布式 svn集中式
-
控制版本
1.git简介
1.1 git的由来
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比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了
1.2 集中式和分布式
SVN是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?
集中式版本控制系统:版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。例如:中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆【缺点:必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊】
分布式版本控制系统:根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。如果是一个团队合作工作,比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
二者之间的区别:和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
实际情况:使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
当然,Git的优势不单是不必联网这么简单,后面我们还会看到Git极其强大的分支管理,把SVN等远远抛在了后面。
2.安装 git
git:查看是否已经安装
sudo apt install git :安装
3.创建版本库
3.1什么是版本库
版本库又被称为仓库,【repository】,初期可以理解为一个目录,这个目录里面管理的文件都可以称为被git管理起来的,每个文件的修改,删除等的操作git都能进行跟踪
3.2创建版本库
git init:将一个普通目录变成版本库 会在项目中新增一个 .git文件夹
在桌面上新建一个test文件夹. 进入test文件夹,单击右键选择git bash here 输入 git init 命令 (该命令表示初始化仓库) 执行完毕后,会自动创建一个 .git文件夹. #注意:也不一定目录是空的,但是为了安全起见,最好以一个空的目录作为版本库
3.3把文件添加到版本库
注意:所有的版本控制系统都是跟踪的是文件的改动
git add filename : 将文件添加到缓存区/暂存区
git commit -m "日志" :提交文件到版本库【仓库】
1.创建一个文件 a.txt 2.git add a.txt 将文件提交到暂存区 3.git commit -m "提交记录的描述" 将文件提交到仓库 第一次提交的时候会提示: *** Please tell me who you are. *** 请告诉我你是谁。 #不知道主人是谁,则需要配置用户名和邮箱 #注意:用户名和邮箱来自gitee上的注册 运行 git config --global user.email "自己在gitee或者 github绑定的邮箱" git config --global user.name "自己在gitee或者github设置的用户名" 来设置您账号的缺省身份标识。 如果仅在本仓库设置身份标识,则省略 --global 参数。 fatal: 无法自动探测邮件地址(得到 'ijeff@Rock.(none)')问题:为什么Git添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,如下:
git add b.py git c.docx git commit -m "提交b.py和c.docx" git add . 表示添加所有的文件 (慎用) #总结:add一次添加一个文件,commit可以一次提交多个文件
4.时光穿梭机【覆水可收】
git status:查看仓库当前的状态
git diff filename:查看仓库具体的改动
git status git diff 文件名: (建议在git add和git commit之前查看文件做了哪些修改) git diff b.py 查看b.py文件和修改前有哪些区别
4.1版本回退
工作原理:每当修改一个文件,并且使用commit提交之后,其实就相当于保存了一个快照
需求:回退到上一个版本
补充:要回退版本,首先需要知道当前处于哪个版本,在git中,用HEAD表示当前版本,上一个版本是HEAD^,上上个版本是HEAD^^,如果向上找100个版本,则表示为HEAD~100
git log 显示提交的日志 git log --pretty=oneline 以简化的形式显示提交的日志记录 git reflog 用来记录你的每一次命令 git reset --HARD^ 表示回退到上个版本 git reset --hard 版本号【commit id】(常用) git reset --hard bd06e2b14e818971e85daa67be64268d4d7ec150 回退到指定的版本总结:
HEAD指向的是当前版本,git在历史的版本之间来回切换,使用git reset --hard commitid
切换版本前,可以使用git log查看提交历史记录,以便于确定回到哪个历史版本
要重返未来,用git reflog查看历史执行过的git操作,从上往下寻找第一个commit的操作,则是未来的最新的版本
4.2工作区和暂存区
工作区:working Driectory,就是你电脑中的能看到的目录【hello】
版本库:工作区中有一个隐藏的目录 .git,该目录就是git中的版本库
版本库中存放了很多的数据,其中包括暂存区【缓存区,stage或者index】,还有git为我们自动创建的第一个分支master【主分支】,以及指向master的一个指针HEAD
往git版本库中添加文件,分为两步:
a. git add,实际是将文件的修改添加到暂存区中
b. git commit .实际是将暂存区的文件修改提交到当前分支【主分支】
4.3 管理修改
注意:git跟踪管理的是修改,并非文件
git status git add git commit -m "提交描述信息"
4.4撤销修改
git checkout -- 文件名
4.5删除文件
在git中,删除文件也是一个修改操作
先在本地目录删除 ** 文件 git add . git commit -m "删除 ** 文件" 或者(了解) git rm ** 文件 git commit -m "删除 ** 文件"
本地仓库命令:
git init : 创建本地仓库,会生成.git文件夹
git add : 将工作区的修改添加到暂存区
git commit : 将暂存区的所有内容 提交 到仓库分支
git status : 查看仓库状态
git diff : 查看工作区和本地仓库的区别
git log (git log --pretty=oneline) : 查看提交记录
git reflog : 查看所有操作(包括commit 和 reset)
git reset --hard HEAD^ (git reset --hard a3cef73) : 版本回退(版本跳转)
git rm a.txt: 删除文件
git checkout -- a.txt : 撤销工作区的修改
git reset HEAD a.txt :撤销暂存区的修改
5.远程仓库
5.1建立远程仓库的准备工作
步骤:
a.创建github账号 或者 gitee账户
b.生成ssh key【密钥,建立本地和网络之间的连接】
命令:ssh-keygen -t rsa -C "github的注册邮箱"
c.添加到github
d.检测是否添加成功
命令: ssh -T git@github.com
演示命令: 生成公钥 ssh-keygen -t rsa -C "156121576@qq.com" Enter file in which to save the key (/home/ijeff/.ssh/id_rsa): Created directory '/home/ijeff/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/ijeff/.ssh/id_rsa. Your public key has been saved in /home/ijeff/.ssh/id_rsa.pub. The key fingerprint is: SHA256:o/KqM3kWKnQBZL8xGGyxhO6n82YJpN6YQfTcZMbp/3E 123456@163.com The key's randomart image is: +---[RSA 2048]----+ |+*. . . | |+== * | |+o++* | | + ++o | |= .. . S | |.= o. o o E | |o Xoo.. . o | |.*==oo . | | .*B... | +----[SHA256]-----+ 下面打开公钥生成的路径,找到 c/Users/chenbingjie/.ssh/id_rsa 文件夹 将里面的id_rsa.pub文件中的内容复制, 粘贴到gitee官网的添加公钥的位置.
5.2.将本地仓库和远程仓库联系起来
关联远程仓库: git remote add origin(远程仓库的名字) git@gitee.com:jiebingchen01/dahouse.git
推送本地仓库到远处仓库: git push [-u] origin master(远程分支的名字)
从远处仓库拉取分支到本地: git pull origin master
演示命令:
git remote add origin(远程仓库的名字) git@gitee.com:jiebingchen01/dahouse.git git add REDEME.md git commit -m "第一次提交REDEME.md" git push [-u] origin master总结:
要关联一个远程仓库,使用命令 git remote add origin git@github.com:username/repoName.git
关联成功之后 ,使用命令git push -u origin master第一次推送master分支的内容到远程仓库
以后,每次本地提交之后,只需要使用命令git push origin master推送最新的修改【本地修改----> add到暂存区 ---> commit到本地仓库 ---> push到远程仓库】
5.3从远程仓库克隆
git clone git@github.com:username/repoName.git 克隆远程仓库到本地(会自动创建本地仓库并关联)
git clone git@github.com:username/repoName.git 把远程仓库的项目克隆到本地 #克隆到本地之后,就可以任意修改本地工作区中的文件,修改完成之后,首先将修改add到暂存区,然后将暂存区中的修改提交到本地仓库,最后将本地仓库中的修改推送到远程仓库
6.分支管理
6.1.创建和合并分支
查看分支 git branch master 是主分支 所有的项目全部在主分支上面,其他分支的代码全部合并到主分支. 开发代码不会直接在master分支上面开发. git branch 分支名 git checkout -b 分支名 创建一个新分支并且切换到新分支上面去 * dev 里面的 * 表示在哪个分支上面 git checkout 分支名 切换到指定的分支上面去 git branch -d 分支名 删除分支 git merge 分支名 合并分支 一定要先切换到master主分支以后,再去合并分支总结:
git鼓励大量使用分支
查看分支:git branch
创建分支:git branch dev
创建并切换分支:git checkout -b name 【-b创建分支并且同时切换到子分支下】
切换分支:git checkout name
合并某个子分支到当前分支:git merge name
删除分支:git branch -d name
A程序员和B程序员开发同一个项目的不同模块
第一天:
A程序员写完后,提交push代码到远程仓库,打卡下班了
B程序员要先把A的代码拉下来pull,改bug后,再提交push到远程仓库,打卡下班
第二天:
A程序员开始写代码前,要先拉下来pull
6.2解决冲突
Auto-merging a.txt CONFLICT (content): Merge conflict in a.txt Automatic merge failed; fix conflicts and then commit the result. <<<<<<< HEAD hello world! master ======= 马云说:好个锤子!顶你个肺! dev >>>>>>> dev 解决完冲突后,一定要重新提交到仓库中去 git add 文件名 git commit -m "解释" git merge 分支名
总结:
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph命令可以看到分支合并图
6.3分支合并策略
合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
总结:
master分支应该是非常稳定的,仅仅使用master分支发布版本,平时不在上面干活
比如:每个人都在dev的分支上干活,每个人都有自己的分支,时不时的向dev上合并代码就可以了
比如:发布1.0版本,再把dev上的代码合并到master上面
合并分支时,加上--no-ff参数表示使用普通模式进行合并,合并之后可以查看历史 记录,而Fast-Forword快速模式没有历史记录
6.4 远程仓库分支管理
-
先创建远程仓库, 在远程仓库中创建2个master的子分支dev, dev2
-
然后创建2个本地仓库, 和远程仓库关联, 并分别拉取2个自分支的内容:
# 第一个本地仓库: git remote add origin 远程仓库地址 git pull origin dev:master # 将远程仓库origin的dev分支拉取到本地master分支 # 第二个本地仓库: git remote add origin 远程仓库地址 git pull origin dev2:master
-
分别在2个本地仓库中添加新文件, 并执行git add 和git commit
-
上传到远程仓库指定分支:
# 将本地仓库的master分支push到远程仓库的dev分支 git push origin master:dev
子分支同步父分支代码
git merge master
7.标签管理
7.1创建标签
1.首先切换到要打标签的分支上面 git checkout 分支名 2.创建标签 git tag 标签名
7.2 操作标签
1.查看标签信息 git show 标签名 2.查看所有的标签 git tag