代码版本控制
我们在项目开发过程中,经常会需要将代码回退到前一天或者其他的某个时间节点,这个时候我们可以针对情况对代码进行删除等操作,但是这种删除的操作一般代价都比较大,成本比较高,这个时候我们就可以对我们的代码进行版本控制,当然我可以手动的在开发发某个功能之后,将代码文件都保存一份,然后需要更改回退的时候再将保存好的代码复原,但是这样手动的代码版本控制比较麻烦,出错几率高。
在这里给大家介绍两个代码版本控制工具:git/svn
git 和 svn 的区别
svn是集中式管理方式,类似于中央集权制,svn会有一个中央服务器,所有的代码的版本都是管理在中央服务器的,所有开发者都会从中央服务器去选择下载想要的版本的代码,也会将写好的代码进行提交
svn的缺点也很明显:1. 代码版本管理依赖于中央服务器,每个客户端无法在本地进行代码的版本控制 2. 一旦中央服务器奔溃(宕机)甚至数据泄露或者误删的话,整个项目的代码都没办法找回了
git是分布式管理方式, 每一台客户端都可以看作一个中央服务器,客户端就可以在本地就进行代码版本管理,为了协同合作和代码保护有时也会需要创建一个远端仓库,因为每个客户端其实都会保留完整的代码版本库,所以安全性大大提升。
git 基本操作
我们从官网下载了git安装包后进行安装,git也是依赖于命令行工具来执行任务的,但是安装的时候会自带一个GUI这样的可视化界面,市场上也有很多可视化GIT操作,例如tortoisegit, 但是一个好的程序员都不使用可视化工具
git的命令行工具中会使用一些linux的操作命令,在这里利用一个小小的情书项目来学习git
首先我们创建好项目目录之后,先去进行git仓库的初始化(创建版本管理)
git init
执行完成后会出现如下的命令
Initialized empty Git repository in F:/BK-1811/front-end-project/git/love-letter/.git/
初始化了一个空的git仓库在 …/.git/ 也就是说项目目录中的.git文件夹其实就是这个项目的本地仓库,里面会保存项目的每个版本的代码
然后进行了代码的开发,开发到一定的阶段,准备提交一个版本(提交到本地仓库-> .git)
git add .
上面的命令的意思: 将项目目录中的所有的代码提交到缓存区里,接下来执行这样的命令
git status
这个命令是查看一个当前的git的状态,我们可以看到的是
On branch master
No commits yet
Changes to be committed:
(use “git rm --cached …” to unstage)
new file: introduce.md
new file: love-letter.md
这描述着还没有提交,在缓存区里已经有了一些新文件了
接下来把缓冲区里的文件进行一个提交,提交到本次仓库中(.git),并且做出注释:
git commit -am ‘在这里写此次提交的注释’
注意,这个时候会有一个警告:
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name “Your Name”
to set your account’s default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got ‘Administrator@DCR8WCBA96DBJX9.(none)’)
大家要注意,git进行版本管理的时候,必须得配置一个用户名和邮箱,这样git才能知道操作者是谁,才能运行我们提交
git config --global user.email "murlin@aliyun.com"
git config --global user.name “ergouzi”
接下来就会出现这样的情况:
[master (root-commit) 8f5a228] 我去抽烟了,此次提交的只是写好了情书的开头,个人介绍中写个了名字
2 files changed, 8 insertions(+)
create mode 100644 introduce.md
create mode 100644 love-letter.md
8f5a228是此次提交的版本号,显示了此次提交的注释和此次提交的代码的变化
这次提交完成后,我们去抽烟了,抽烟回来后继续开发代码,开发完成后准备吃饭,所以再来一次提交
git add .
git commit -am ‘…’
[master 74e4f4c] 先去吃饭吧,刚刚写了一句
2 files changed, 4 insertions(+), 2 deletions(-)
接下来我突然想看一下前几次的提交了,所以我们执行:
git log
commit 74e4f4c636e7710fa0f878d74a641b2de502e74a (HEAD -> master)
Author: ergouzi murlin@aliyun.com
Date: Fri Sep 14 10:38:38 2018 +0800
先去吃饭吧,刚刚写了一句
commit 8f5a228d55e7d2c1919e9b895c26a30248842fe8
Author: Erioser 983357618@qq.com
Date: Fri Sep 14 10:26:27 2018 +0800
我去抽烟了,此次提交的只是写好了情书的开头,个人介绍中写个了名字
查看历史版本后,我们吃饭了,吃完饭回来继续开发,但是这次开发可能会存在一些问题,我们没有发现,准备再提交一次后回家
穿插一句,执行git diff命令的时候,可以查看一些当前工作区与暂存区(.git)的代码区别
我们第二天上班的时候,发现代码中有大问题,不能运行,我们必须回退到上一个版本了,我们先利用git log 查看一下有哪些版本
我们准备回退到上一个版本,所以我们记录了版本号 74e4f4c636e7710fa0f878d74a641b2de502e74a,准备回退
git reset --hard HEAD^ --------->回退到上一个版本
git reset --hard HEAD^^ --------->回退到上上个版本
git reset --hard HEAD~N --------->回退到第N个版本 N是一个整数
git reset --hard 版本号 --------->回退到指定版本
注意,版本号回退的方式不需要把整个版本号都写上,写上前6,7位
我本来共有三个版本,最近的第三个版本是坏的,所以我应该回退到第二个版本,但是一不小心回退到了第一个版本,现在我要想办法再回到第二个版本,此时我们git log 的时候已经看不到第二个版本了,所以我们执行
git reflog
这样,我们就能看到我们每一次的版本操作,就能找到第二个版本的版本号了:74e4f4c
git reset --hard 74e4f4c
到这里为止,git的基本操作就介绍完了,更多详细的内容请查看廖雪峰GIT教程
GIT 分支操作
目前我们的项目中有两个功能模块: love-letter.md / introduce.md ,刚才love-letter写错了,想回退的时候,结果introduce也回退了,所以我们想,能不能分开的对这个功能模块进行管理呢?
git中提供了分支管理这样的机制,我们可以针对不同的功能模块利用不同的分支来管理(branch)
首先针对项目中的这两个功能模块创建对应的分支:
git branch 分支名
git branch love-letter
git branch introduce
我们执行git branch命令就可以查看当前本地所有的分支已经当前所处的分支
introduce
love-letter
- master
master是git init之后就自动创建好的本地主分支,上面的是我们刚刚创建的本地子分支,master前面有个小*号,这个符号代表master是当前所处的分支。
接下来,我们准备去开发love-letter,所以我们要切换到love-letter分支
git checkout 分支名
git checkout love-letter
切换分支后,进行操作之后,记得也要提交,并且,分支里面的各种操作对于其他分支来说都是独立的,彼此之间不能相互控制版本
现在我们的分支处理号了,再love-letter分支中只管理love-letter.md,introduce也是如此,但是,所有的代码其实还是存在于主分支的,也就是说主分支上才是完整的项目
接下来,我们就可以再各个分支上进行对应的项目开发, 当我们项目中某个功能模块开发完成后,比如introduce已经开发完成了,需要切换回master分支,因为master分支上的代码才是真正的项目代码,最终上线的代码都在master中
我们需要将master中的关于introduce的代码和introduce分支中最终的代码进行合并
合并分支: git merge 分支名 ,在A分支中执行 git merge B,就是把B分支的代码合并到A分支来
当我们合并了分支之后,可能master中有a这个文件,但是在B分支中没有a这个文件,所以合并后可能a这个文件就被误删,这个时候执行:
git log --diff-filter=D --summary
可以看到是哪个版本在提交的时候删除了a,假设是486532版本,就执行
git checkout 486532~1 a.jpg
这样的话,a文件就回来了,然后再去提交
其实刚才的情况主要是因为,master中有两个文件,但是在分支中都各只有一个文件,导致合并过来的时候出现了问题,所以,其实我们应该保证,分支中的代码和master中的文件应该是只能多不能少
尽量保证进入新创建的分支后,别删除之前的其他的文件,不然的话在和主分支合并的会误删文件
当在A中修改了某个文件,在master中合并了,在B中也修改了这个文件,在master中合并的时候会出现冲突>>>><<<<<=====>>>>>描述,更改的地方,所以可以利用编辑器来处理冲突,也可以手动的删去不想要的内容,冲突解决完成后,才能再次提交。。。
GITHUB的基本介绍和使用
在开发的时候,我们一般都需要一个远端仓库来在协同开发的时候做一个中转,也可以在个人开发的时候在远端仓库保存一份代码。
一般情况,要么公司会有咱们的运维工程师去搭建公司自己的git服务器,要么公司就会采用现有的一些较大的git代码托管平台
现成的第三方代码托管平台: GitHub, GitLab, 码云…
因为GitHub上的代码一般都是开源的,针对公司业务来说不太安全,所以国内公司的项目大部分还是使用的GitLab
Github的使用方式:
注册账号登陆之后,首先先去配置一个ssh key,我们建好仓库之后与远端仓库进行连接的时候,需要使用的连接方式有两种:http,ssh,更多的使用的是ssh,但是在使用之前需要在设备中生成一个sshkey配置到当前的github账号中
- 创建一个仓库
- 配置ssh key
在git bash 中执行如下命令:
ssh-keygen -t rsa -C “github账号的邮箱”,生成好之后默认是保存在 /c/Users/Administrator/.ssh/id_rsa.pub中,将里面生成好的key,在github网站中,点击setting -> SSH and GPGkey -> new SSH key - 在git bash中配置全局email,name,为了和github远端仓库做联系,我们将email和name配置成github账号的email和name
- 在这里玩的时候有两种方式,如果我们加入项目组比较迟的话,我们使用该仓库的方式:
克隆下来这个仓库,在本地开发,开发完成后再提交到远端仓库
我们也可以这样来,先再本地git init创建本地仓库,开发了一部分之后,再将本地仓库和远端仓库进行关联
首先我们尝试直接克隆远端仓库:
在本地执行 git clone git@github.com:Erioser/1811-demo.git,然后再本地克隆下来的仓库进行开发,然后提交等操作
这种方式是属于先建立仓库,再去开发。
有的时候是先开发,再本地先建立了项目,后建立的远端仓库,方式应该是这样的:
项目环境搭建好之后,在项目目录中执行git init初始化了本地仓库之后,先add/commit,提交一个版本
将本地仓库与远端仓库进行关联:
git remote add origin 远端仓库的地址
将初始化的项目代码提交到远端的主分支上:
git push origin master
但是注意,我们在每次push代码到远端的时候应该先git pull一次,将远端代码拉下来之后合并一下,没问题之后再push
git push -u origin master -f 强制推上
所以说,上面的介绍只是在说,可以先建立仓库,再clone,再开发,也可以先开发,再建仓,再remote
项目环境搭建好之后,在项目目录中执行git init初始化了本地仓库之后,先add/commit,提交一个版本
将本地仓库与远端仓库进行关联:
git remote add origin 远端仓库的地址
将初始化的项目代码提交到远端的主分支上:
git push origin master
但是注意,我们在每次push代码到远端的时候应该先git pull一次,将远端代码拉下来之后合并一下,没问题之后再push
git push -u origin master -f 强制推上
当我们git pull 下来的时候可能有有这样的问题:can’t merge unrelated …
其实是因为这个时候本地的仓库和远程的仓库根本就不是同一个项目,所以拉下来的时候没有和本地的合并,所以本地没有README. md,所以提交的时候会出错,我们可以用上面的代码强行推上去,其实也可以在git pull 的时候执行这样的代码git pull --allow-unrelated-histories origin master,在拉下来的时候强行把远端的和本地的合并
所以说,上面的介绍只是在说,可以先建立仓库,再clone,再开发,也可以先开发,再建仓,再remote