简介
Git是目前世界上最先进的分布式版本控制系统
什么是版本控制系统呢?
简单说,它有以下功能
- 备份(记录多个版本文件的功能)
- 记录操作时间线(查看历史操作,进行版本回滚、前进的功能)
- 多端共享代码(代替各种云盘的功能)
- ‘自动’合并(解决多人开发冲突问题)
介绍一下Git和SVN的区别
集中式版本控制系统SVN
版本库集中放在中央服务器,工作时首先要从中央服务器得到最新版本,工作完成后,再推送到中央服务器。集中式版本控制系统必须联网才能工作,如果没网就GG了
分布式版本控制系统Git
Git是没有中心服务器的,每个人机器上都是一个完整的库,平时开发代码时的中央服务器其实和我们自己机器上的库内容基本是完全一样的,工作时完全不需要互联网
去中心化意味着没有权威、没有主力,人人平等。这对社区影响是巨大,Github上的fork功能,允许你fork任何一个你喜欢的项目,接着按自己的喜好修改成自己的项目,或是发起pull request请原作者merge你的功能到他们项目里去(这同样也得益于Git另一项与SVN很大不同的功能——分支策略),而且大多数开源项目都会鼓励你去fork它们。这里面没有权威,没有主从,所有人只要有兴趣都可以在其他人的基础上去构建更强大或是更有领域针对性的项目
安装
安装包去Git官网下载就好了
安装完毕后,在桌面或任意文件夹右键就会发现多了两个选项
证明我们安装成功了
在开始菜单中找到Git Bash点开
我们还需要配置用户名和邮箱作为标识
什么信息也没回馈就代表成功了(下面介绍的命令也是一样)
git config --global
是全局配置
当然我们可以针对某个库设置特定用户名和邮箱
管理
首先我在桌面创建了一个文件夹demo作为我们的项目文件夹
内部创建了一个foo.txt的文件
在文件夹内部Git Bash(这样比较方便,cd定位盘符太麻烦,pwd
命令查看当前目录)
输入命令 git init
(创建本地仓库)
现在我们的目录就变成了Git可以管理的仓库
我们把文件夹选项改成显示隐藏文件就会发现
git为我们在目录中创建了一个.git的文件
它就是跟踪管理版本的奥秘所在
不要胡乱删改它里面的文件就好
基本概念
为了更好的理解我们接下来匪夷所思的操作
我们有必要了解一下Git基本概念
工作区Working Directory
我们电脑上可以显示的目录就是工作目录
版本库Repository
隐藏文件.git就是版本库,它也叫做仓库
仓库里所有文件都通过Git来实现版本管理,Git都能跟踪并记录在该目录中发生的所有更新
版本库中最重要的就是stage/index缓存区和Git为我们创建的主分支master
还有一个指向master的指针head
缓存区Stage
缓存区就是版本库内的一个区域,用来缓存我们的修改
此外还要注意,所有版本控制系统,只能够跟踪文本的改动,例如txt、html、css、js等等
但是图片、音频等二进制文件,它只能够知道文件大小变动了多少
至于变动了什么,它们无法知道
工作流程
我们Git大体的工作流程就是这样地
git add
把文件从工作区添加到版本库中的缓存区git commit
提交代码,把缓存区所有内容提交到当前分支
每次提交后系统都会记录一下这次操作的相关信息
形成一张张“快照”
通过它们我们就可以实现“回溯”
内部其实就是指针与链表
基本操作
了解了相关概念以及流程之后
我们来看看具体的操作
首先我在我们工作区的foo.txt文件内输入:aaa
文件提交
1.工作区→缓存区
输入命令:git add <filename>
将foo.txt文件添加到仓库的缓存区
如果想要将工作区全部文件添加到缓存区就使用git add .
2.缓存区→主分支
输入命令:git commit -m 'xxx'
-m是message的意思,后面的字符串就代表本次提交的注释
查看状态
完成这两步后,我们就算是已经提交foo.txt了
使用git status
命令可以查看仓库状态
(commit提交前后,最好使用一下这个命令)
由于我对foo.txt文件的修改,文件夹中产生了备份文件foo.txt.bak
所以git提示我们它还没有上传它
没关系,我们不需要这个文件删掉就好了
这回Git提示我们工作区干净了,没什么要提交的了
增删信息
现在我在foo.txt中再添加一行bbb
恩关了文件夹后我忘了改什么了,怎么办?
使用命令:git diff <filename>
可以清晰的看出我们所作出的修改
这回可以安心提交了,同样git add
、git commit
版本查看
继续向foo.txt文件中添加一行ccc,然后提交到本地仓库
到目前为止,我们的仓库中已经有了三个版本的foo.txt了
使用命令git log
查看我们的版本信息
黄色的那几行就代表版本号
(GG我第一次提交注释first submit中间居然没加-,强迫症)
如果大家觉得乱七八糟的东西太多
可以输入:git log --pretty=oneline
只显示版本号和版本注释
版本回溯
终于到了这一步(不知道叫回溯对不对)
如果我们想要回到上个版本
请输入:git reset --hard HEAD^
如果我们想要回到上上个版本
请输入:git reset --hard HEAD^^
如果我们想要回到10000个版本之前
可以敲一天“^”
不过更简便的操作是git reset --hard HEAD~10000
当然我们很少这么丧心病狂的回溯
现在我们来试着回溯一步
好了Git提示我当前穿越成功了
使用cat <filename>
查看文件验证一下
果然这就是我们foo.txt的第二个版本
历史记录
再次查看版本信息
我们发现第三次版本的信息没有了
不用担心,既然我们能穿越回来也能穿越回去
不过稍微麻烦一点点
要想回到最新版本foo-3.0,我们需要知道它的版本号
但问题是版本信息查不到了
这时需要我们查看历史记录
命令:git reflog
看到黄字没,猜猜那是神马
没错就是版本号的前7位
有了它我们就可以穿越回去了
版本前进
前进版本命令:git reset --hard <version>
如此一来我们便可以回到最新版本
撤销修改
现在我们当前的最新版本foo-3.0又添加了一行ddd
可是我又后悔了,我想要撤销
目前我们有两种办法
- 直接手动修改,或者Ctrl+Z
- 版本回溯
第一种简单粗暴,我们的例子实在太简单了,所以一个Ctrl+X就解决了
但实际开发中可没这么轻松
第二种又比较麻烦,我不想这么做
那怎么办?
我们可以使用git checkout -- <filename>
这个命令的作用就是讲我们在工作区所作出的改变全部撤销(恢复到上一次commit)
不过如果在此之前我们已经将工作区保存到缓存区了,那么只能恢复到缓存的状态(恢复到上一次add)
怕大家不理解,我再演示一下第二种情况
在foo.txt中再次输入ddd
但是这次我先把它保存到缓存区
然后输入撤销指令
我们发现撤销失败了,因为它恢复到我们缓存区的状态,依然没有任何变化
文件删除
在这个控制台中
我们还可以删除文件
命令:rm <filename>
再次查看文件发现确实不在了
如果我们没有提交到缓存区同样使用撤销命令恢复文件
分支
如果我们在开发过程中遇到了非常复杂的任务
写了一半后到深夜了,提交吧,代码不完整其他人没法开发;不提交,还可能丢失代码
所以我们需要利用分支branch
在自己的分支上工作,什么时候完成,什么时候合并分支
不影响别人,也更加安全
分支原理
-
我们每经过一次commit提交就是一个时间点,Git将这些时间点串联成一条时间线
最开始只有默认的master主分支,HEAD指针指向当前分支的当前版本
-
现在我们创建自己的分支dev(命令:git branch dev),Git会开辟一个指针,它会指向master指向的版本
-
有了dev分支我们还需要切换到dev分支(命令:git checkout dev),此时HEAD指针指向dev
-
这样我们在dev分支上开发,只有dev指针在动,master指针没有动
-
当我们在dev分支上完成任务后,就需要将它合并到主分支master
合并前需要将分支切换回master(命令:git branch master)
-
HEAD指针重新指向了master主分支,然后我们就可以合并了(命令:git merge dev)
-
这是正常的情况,如果在合并的时候发生了冲突,你修改了文件file,但是你的另一个朋友也修改了file中的相同语句,并且上传到了master主分支,这时就需要手动解决冲突调整代码后,再合并
-
合并完成dev分支就没有用了,删除即可(命令:git branch -d dev)
分支策略
在开发中,我们使用分支管理应该遵循以下原则
- master主分支仅用来发布新版本,平时不要在master分支上开发,master分支应与远程仓库保持同步
- 平常开发都在dev分支上,正式版本发布前,把dev分支合并到master上,dev分支也应与远程保持同步(git push/git pull解决冲突)
- 团队每位成员都在本地的各自dev分支上干活,不时地往远程dev分支上push/pull(git push/pull解决冲突)
分支使用
上面的分支原理已经把分支命令都介绍的差不多了
我再通过例子把流程扫一遍
现在我重新创建一个demo文件夹
内部有一个文档foo.txt,内容aaa
add、commit提交到本地仓库
现在主分支上就有我们的foo-1.0了
创建与切换分支
其实分支的创建和切换是可以通过一个命令同时完成的
现在我们创建一个叫做dev的分支并切换到它上面
输入命令:git checkout -b dev
它相当于下面俩个命令的并集
创建分支dev git branch dev
切换分支dev git checkout dev
查看分支
创建并切换完毕后,我们可以来查看全部分支
输入命令:git branch
可以看到蓝字dev就表示我们当前在dev分支
我们输入的命令显示了全部分支,并且当前分支dev用绿字高亮了
合并分支
现在我们在foo.txt添加一行bbb
然后add、commit提交到本地仓库
dev分支的任务就算完成了
合并前需要切换回主分支
输入命令:git checkout master
此时的foo.txt仍然是我们的foo-1.0版本
也就是说肯定没有我们添加的bbb
现在可以合并了
输入命令:git merge dev
现在主分支就是我们的foo-2.0版本了
删除分支
查看一下分支,此时dev还是存在的
我们不需要它删掉就好了
输入命令:git branch -d dev
合并分支Git默认使用Fast forward模式,删除分支后,分支信息消失
合并时如果使用命令git merge --no-ff -m <comment> <branch>
可以禁用Fast forward模式
这样删除分支,信息也不会丢失
解决冲突
我们当前的foo-2.0内容是aaabbb
现在我重新创建一个dev分支,添加ccc,提交add、commit
再回到master主分支,添加ddd,提交add、commit
现在我再合并分支
Git提示我们产生了冲突
查看仓库状态
Git提供给了我们冲突的详细信息
此时我们再查看文件
它向我们标记了不同分支的内容
这样我们就可以手动修改代码解决冲突了
(统一master分支和dev分支的代码)
Github远程仓库
Git的远程仓库也就是Github
首先我们需要注册Github账号
不过注册后还没完,要向让本地仓库和远程仓库建立连接
我们需要设置SSH加密,SSH 是建立在应用层基础上的安全协议
创建SSH Key
打开你的用户主目录
看看有没有这两个文件
如果没有的话,打开命令行
输入命令:ssh-keygen -t rsa –C “email@xx.com”
后面输入你自己的邮箱
如果对网络有一些了解,id_rsa是私钥不能泄露给别人,id_rsa.pub公钥无所谓
有了这两个文件后
登录Github账号,进入右上的设置选项
在左侧的Personal settings
点击SSH and GPG keys
然后点击右侧的New SSH Key
输入标题后,将id_rsa.pub公钥内容原封不动的拷贝到Key栏里,最后Add SSH Key即可
如果看到了这个恭喜你成功了
添加远程库
上面我们也说到了,开发项目我们的本地Git仓库最好和远程Github仓库保持同步
同样在Github中,在右上找新建仓库
输入仓库名、可选的描述等等就可以创建了
然后我们就可以将这个空仓库克隆到本地
本地开发完,又可以同步到Github
本地库→远程库
首先,我们按照Github的提示
在本地的demo仓库中运行命令
git remote add origin <url>
(在控制台中Shift + Ins粘贴)
(输入命令时必须是 git init
由Git管理的仓库)
将本地库的master分支同步到远程库的master分支
输入命令:git push -u origin master
命令中的-u其实是吧本地库和远程库关联起来了
所以我们以后再同步的时候
只需输入命令:git push origin master
就可以了
现在我们再登录Github就可以发现远程库已经更新了
远程库→本地库
刚才我们从本地库同步到远程库
现在我们从远程库克隆到本地库
我把本地的demo仓库删掉
在Github中我们还可以找到这个地址
输入命令git clone <url>
克隆远程库的代码到本地
访问网页
如果我们想要访问自己远程库的网页怎么做呢?
很简单,在Github中创建新分支“gh-pages”
这样我们就可以访问自己的页面了
Git常用命令
最后最后时间不早了
感觉还是有好多东西没总结
日后在其他文章再说吧
总结一下Git的常用命令,有的还没讲到
命令中我使用了一些特殊含义词汇如下
描述 | 含义 |
---|---|
<num> | 数字 |
<url> | 地址 |
<filename> | 文件名称 |
<branchname> | 分支名称 |
<version-id> | 版本号 |
<comment> | 注释字符串 |
命令 | 含义 |
---|---|
mkdir <filename> | 创建空目录 |
cat <filename> | 查看文件内容 |
pwd | 显示当前目录的路径 |
git init | 把当前的目录变成git管理仓库,生成隐藏文件.git |
git add <filename> | 工作区某文件添加到缓存区 |
git add . | 工作区文件全部添加到缓存区 |
git commit –m <comment> | 提交文件 |
git status | 查看仓库状态 |
git diff <filename> | 查看文件修改内容 |
git log | 查看历史记录 |
git reset --hard HEAD^ | 版本回溯(回退次数为^个数) |
git reset --hard HEAD~<num> | 版本回溯n次 |
git reset --hard <version-id> | 版本前进 |
git reflog | 查看历史记录的版本号 |
git checkout -- <filename> | 撤销文件在工作区的修改 |
git rm <filename> | 删除文件 |
git remote add origin <url> | 关联远程库 |
git push –u origin master | 将当前master分支关联并推送到远程库 |
git push origin master | 将当前master分支推送到远程库 |
git clone <url> | 从远程库克隆 |
git checkout <branchname> | 切换到某分支 |
git checkout –b <branchname> | 创建并切换到某分支上 |
git branch | 查看当前所有的分支 |
git merge <branchname> | 在当前的分支上合并某分支 |
git branch <branchname> | 创建某分支 |
git branch –d <branchname> | 删除某分支 |
git stash | 隐藏当前工作待恢复现场后继续工作 |
git stash list | 查看所有被隐藏的文件列表 |
git stash apply | 恢复被隐藏的文件,但内容不删除 |
git stash drop | 删除文件 |
git stash pop | 恢复文件的同时也删除文件 |
git remote | 查看远程库的信息 |
git remote –v | 查看远程库的详细信息 |
git push origin <branchname> | 将某分支推送到远程库对应的远程分支上 |