一、概述
1.Git是什么?
Git是目前世界上最先进的分布式版本控制系统
2.集中式vs分布式
集中式版本控制系统,版本库是集中存放在中央服务器的。而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。集中式版本控制系统最大的弊端就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟。
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
3.CVS作为最早的开源而且免费的集中式版本控制系统,由于自身设计的问题,会造成提交文件不完整,版本库莫名其妙损坏的情况。而SVN(同样开源和免费)修正了CVS的一些稳定性问题,是目前用得最多的集中式版本库控制系统。。
二、在Windows上安装Git
在Windows上使用Git,可以从Git官网直接下载安装程序,(网速慢的同学请移步国内镜像),然后按默认选项安装即可。
安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
1.测试是否安装成功
//cmd打开命令输入下面内容
git --version //显示版本号
2.安装成功之后先注册Git账户
$ git config --global user.name "Your Name" //用户名
$ git config --global user.email "email@example.com" //邮箱
3.使用码云(国内的Git托管服务)
创建私有仓库来存放自己的代码,让本地代码和线上代码通过git关联上,一旦本地代码丢失可通过线上代码进行回溯或者恢复。
设置关联:公钥和私钥打通关联
点击--设置--SSH公钥
打开git bash(相当于进入Liuxs)
ssh-keygen -t rsa -C "954029632@qq.com" //邮箱尽量与注册的邮箱保持一致
cat ~/.ssh/id_rsa.pub //查看你的 public key
在SSH公钥里面将public key填入
打开项目管理页面:将线上项目克隆到本地
点击克隆 --选择SSH协议--复制地址--cmd 切换目录 输入下面的指令
git clone git@gitee.com:dell-lee/Travel.git //把线上代码克隆到本地放到当前目录下
4.把文件添加到版本库
所有的版本控制系统,只能追踪文本文件的改动,Git也不例外
//查看新添加的文件
$ git status
//用命令git add 告诉Git,把文件添加到仓库
$ git add .
//用命令git commit 把文件提交到仓库 -m 后面输入的是本次提交的说明,可以输入任意内容
$ git commit -m "add some files"
//将本地代码推到线上仓库
$ git push
打开码云刷新,查看内容线上线下统一。
三、版本回退
1.显示从最近到最远的提交日志
$ git log //显示提交的日志
//嫌输出信息太多可使用下面这条指令
$ git log --pretty=oneline
2.启动时光穿梭机,将版本回退
首先,Git必须知道当前是哪个版本,在Git中,用HEAD表示当前版本,上一个版本为HEAD^,上上一个版本为HEAD^^,
当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100。
现在,我们要把当前版本回退上一个版本,使用git reset 命令
$ git reset --hard HEAD^
这时,再用git log查看现在版本库的状态,发现最新的那个版本已经看不到了!只要上面的命令行窗口还没被关掉,可以找到最新版本的commit id ,即可指定回到某个版本
$ git reset --hard 1094a//id没必要完全写完,写入部分git会自动搜索
你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^
回退到HEAD^
版本时,再想恢复到HEAD^
,就必须找到HEAD的
commit id。Git提供了一个命令git reflog
用来记录你的每一次命令
$ git relog
3.撤销修改
1.当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
2.
当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按1操作。
4.删除文件
在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt
到Git并且提交
$ git add test.txt
$ git commit -m "add test.txt"
[master b84166e] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm
命令删了:
$ rm test.txt
这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status
命令会立刻告诉你哪些文件被删除了
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
现在在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm
删掉,并且git commit
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复
$ git checkout -- test.txt
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”.
四、分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
其他版本控制系统如SVN等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。
但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。
1.创建与合并分支
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master
分支。HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。
一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点。
每次提交,master
分支都会向前移动一步,这样,随着你不断提交,master
分支的线也越来越长。
当我们创建新的分支,例如dev
时,Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上
Git创建一个分支很快,因为除了增加一个dev
指针,改改HEAD
的指向,工作区的文件都没有任何变化!
不过,从现在开始,对工作区的修改和提交就是针对dev
分支了,比如新提交一次后,dev
指针往前移动一步,而master
指针不变:
假如我们在dev
上的工作完成了,就可以把dev
合并到master
上。Git怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支
先总结一下可能会用到的指令,稍后实战操作。
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
实战操作:
首先,我们创建dev
分支,然后切换到dev
分支
$ git checkout -b dev
Switched to a new branch 'dev'
//git checkout命令加上-b参数表示创建并切换,相当于以下两条命令
//$ git branch dev
//$ git checkout dev
///Switched to branch 'dev'
然后,用git branch命令查看当前分支
$ git branch
* dev
master
git branch命令会列出所有分支,当前分支前面会标一个 * 号
然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,加上一行
creating a new branch is quick.
然后提交:
$ git add readme.txt
$ git commit -m "branch test"
[dev b17d20e] branch test
1 file changed, 1 insertion(+)
现在,dev分支上的工作完成,我们就可以切换回master分支
$ git checkout master
Switched to branch 'master
切换回master
分支后,再查看一个readme.txt
文件,刚才添加的内容不见了!因为那个提交是在dev
分支上,而master
分支此刻的提交点并没有变:
现在,我们把dev分支的工作成果合并到master分支上:
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge
命令用于合并指定分支到当前分支。合并后,再查看readme.txt
的内容,就可以看到,和dev
分支的最新提交是完全一样的。
注意到上面的Fast-forward
信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master
指向dev
的当前提交,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward
,我们后面会讲其他方式的合并。
合并完成后,就可以放心地删除dev
分支了:
$ git branch -d dev
Deleted branch dev (was b17d20e).
删除后,查看branch ,就只剩下master分支了“
$ git branch
* master
因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master
分支上工作效果是一样的,但过程更安全。
switch
我们注意到切换分支使用git checkout <branch>
,而前面讲过的撤销修改则是git checkout -- <file>
,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch
更科学。因此,最新版本的Git提供了新的git switch
命令来切换分支:
创建并切换到新的dev
分支,可以使用:
$ git switch -c dev
直接切换到已有的master
分支,可以使用
$ git switch master
2.解决冲突
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph
命令可以看到分支合并图