代码版本控制[version control]之Git
如何多人协同开发同一个项目?
目前市面上比较流行的代码版本控制器有: git,svn,csv
1. 使用git管理代码版本
本项目使用git管理项目代码,代码库放在gitee码云平台。(注意,公司中通常放在gitlab私有服务器中)
1.1 Git 的诞生
2005 年 4 月3 日,Git 是目前世界上最先进的分布式版本控制系统(没有之一)
作用:源代码管理
为什么要进行源代码管理?
-
方便多人协同开发
-
方便版本控制
1.2 git与svn区别
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,而干活的时候,用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了。
Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。既然每个人的电脑都有一个完整的版本库,那多个人如何协作呢?比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
svn:
Git:
Git的windows下安装
官网地址:https://git-scm.com/download
详细教程可参考:https://blog.csdn.net/gudujianw/article/details/80965067(巨详细)
1、工作区介绍
就是在你本要电脑磁盘上能看到的目录。
2、暂存区介绍
一般存放在【.git】目录下的index文件(.git/index) 中,所以我们把暂存区有时也叫作索引。
3、版本库介绍
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。git中的head/master是分支,是版本库。
git服务器本地搭建:
cd进入到自己希望存储代码的目录路径,并创建本地仓库.git
新创建的本地仓库.git是个空仓库
cd 目录路径
git init
创建仓库:
配置用户名和邮箱
git config --global user.name 'lisi' git config --global user.email 'lisi@163.com'
查看仓库状态
git status git status –s 简约显示
-
红色表示新建文件或者新修改的文件,都在工作区.
-
绿色表示文件在暂存区
-
新建的
login.py
文件在工作区,需要添加到暂存区并提交到仓库区
上图表示: 暂时没有新文件需要提交到暂存区
添加文件到暂存区
# 添加项目中所有文件 git add . 或者 # 添加指定文件 git add login.py
例如: 创建3个文件 ,并查看状态.
提交到版本库
git commit -am "版本描述"
git diff '文件名'
来查看修改的地方,如下图
查看版本记录:
git log 或者 git reflog 过滤查看日志 git log –p 退出按【q】键 ctrl+f向下分页 ctrl+b 向上分页 显示指定日期之后的日志 git log --after '2018-11-6' 显示指定日期之前的日志 git log --before '2018-11-6' 指定显示指定开发者的日志 git log --author 'lisi'
查看文件状态
针对与文件所处的不同分区,文件所处的状态:
(1)未追踪, 文件第一次出现在工作区, 版本库还没有存储该文件的状态 (2)已追踪, 只要第一次,git add了文件, 文件就是已追踪 (3)未修改, 文件在工作区未被编辑 (4)已修改, 文件在工作区被修改 (5)未暂存, 文件已修改, 但是没有add到暂存区 (6)已暂存, 已经将修改的文件add到暂存区 (7)未提交, 已暂存的文件, 没有commit提交. 处于暂存区 (8)已提交, 提交到版本库的文件修改,只有commit以后才会有仓库的版本号生成
注意:
公司一般使用git管理项目,往往会搭建一个gitlab自己内部管理代码,也有公司选择使用码云的企业版仓库来管理 使用git开发项目时,有时候不一定通过https协议提交代码的。也有的公司是通过ssh协议提交,此时需要生成ssh公钥和提交公钥给仓库。[码云这些官网都会有详细的提示说明] 生成SSH公钥【必须安装git bash才可以使用这个命令,而且还要把git bash添加到系统变量里面】 ssh-keygen -t rsa -C "lisi@163.com" 参考:https://gitee.com/help/articles/4180
注意:
现在我已经对文件做修改了,那么我想查看下历史记录,如何查呢?我们现在可以使用命令
git log
演示如下所示:
git log命令显示从最近到最远的显示日志,我们可以看到最近三次提交,.如果嫌上面显示的信息太多的话,我们可以使用命令
git log –-pretty=oneline
会得到简化的数据:
版本回退操作:
回退版本
方案一: HEAD表示当前最新版本 HEAD^表示当前最新版本的前一个版本 HEAD^^表示当前最新版本的前两个版本,以此类推... HEAD~1表示当前最新版本的前一个版本 HEAD~10表示当前最新版本的前10个版本,以此类推... git reset --hard HEAD^ 方案二:当版本非常多时可选择的方案 通过每个版本的版本号回退到指定版本 git reset --hard 版本号
示例如下图:
取消暂存:
git reset head git reset <file> :从暂存区恢复到工作文件 git reset -- :从暂存区恢复到工作文件
示例如下图:
加入后悔了上一次的回退操作,name我们又怎么回退到之前的最新版本呢??\
如:test1文件中hello_test3的内容要如何恢复呢?我们可以通过版本号回退,使用命令方法如下:
git reset –hard 版本号 ,但是现在的问题假如我已经关掉过一次命令行或者hello_test3内容的版本号我并不知道呢?要如何知道增加hello_test3内容的版本号呢?可以通过如下命令即可获取到版本号:git reflog
示例如图:
Git撤销修改和删除文件操作
撤销修改:分为两种情况
情况1.readme.txt自动修改后,还没有放到暂存区,使用 撤销修改就回到和版本库一模一样的状态。
使用命令:
git checkout — file 可以丢弃工作区的修改
示例如下,我们先向test1中添加 hello test4,然后通过git撤销修改:
情况2. 另外一种是readme.txt已经放入暂存区了,接着又作了修改,撤销修改就回到添加暂存区后的状态。
注意:命令git checkout -- test1.txt 中的 -- 很重要,如果没有-- 的话,那么命令变成创建分支了。
手动操作删除 或者 在命令行下 使用 rm 文件名 删除 都是表示在工作区删除.
对于这种删除,如果还原,则可以使用 git checkout 文件名
示例;增加一个test2的文件(将其添加提交),而后将其删除然后再恢复
情况2:假如我们删除了一些文件,但是已经添加add,但还没有提交commit,我们可以采用如下命令,恢复删除的文件
如果文件已添加到暂缓区,在工作区把文件删除了想要还原,这种操作属于暂存区删除,这种删除无法直接git checkout 文件名 来还原. 如果直接执行git checkout 命令,则报错,如果要还原在暂存区中删除的文件,必须先执行 git reset head
示例如下图:
1) 创建私有项目库
- 如何添加远程库?
现在的情景是:我们已经在本地创建了一个Git仓库后,又想在码云创建一个Git仓库,并且希望这两个仓库进行远程同步,这样码云的仓库可以作为备份,又可以其他人通过该仓库来协作。
首先,登录码云上,然后创建一个新的仓库。如下:
创建私有空仓库以后的界面:
2)将自己的项目关联到码云的空仓库中
目前,在码云上的这个gittest
仓库还是空的,码云告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到码云仓库。
git clone 仓库地址 注意,如果当前目录下出现git仓库同名目录时,会克隆失败。
git remote add origin 仓库地址 添加关联
示例如下图所示:
把本地库的内容推送到远程,使用 git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了 –u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以立刻在github页面中看到远程库的内容已经和本地一模一样了,上面的要输入码云的用户名和密码如下所示:
从现在起,只要本地作了提交,就可以通过如下命令:
git push origin master
把本地master分支的最新修改推送到github上了,现在你就拥有了真正的分布式版本库了。
3) 克隆项目
上面我们了解了先有本地库,后有远程库时候,如何关联远程库。
现在我们想,假如远程库有新的内容了,我想克隆到本地来 如何克隆呢?方法类似,调用此方法即可
git clone 仓库地址
注意,如果当前目录下出现git仓库同名目录时,会克隆失败。
创建与合并分支
在 版本回填退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
首先,我们来创建dev分支,然后切换到dev分支上。如下操作命令:
git checkout 命令加上 –b参数表示创建并切换,相当于如下2条命令 git branch dev 创建分支 git checkout dev 切换到该分支 git branch 查看分支,会列出所有的分支,当前分支前面会添加一个星号。
然后我们在dev分支上继续做demo,比如我们现在在test2.txt再增加一行 hello branch
结果如下图:
demo示例:
现在dev分支工作已完成,现在我们切换到主分支master上,继续查看test2.txt内容如下:
现在我们可以把dev分支上的内容合并到分支master上了,可以在master分支上,使用如下命令 git merge dev 如下所示:
git merge命令用于合并指定分支到当前分支上,合并后,再查看test2.txt内容,可以看到,和dev分支最新提交的是完全一样的。注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。
总结创建与合并分支命令如下:
查看分支:git branch 创建分支:git branch name 切换分支:git checkout name 创建+切换分支:git checkout –b name 合并某分支到当前分支:git merge name 删除分支:git branch –d name
如何解决冲突:
加入我们在分支dev1上添加提交了一行hello dev1,而后又在master上添加了提交一行hello master,此时如要合并分支,则会报错,那该如何解决?
demo如下:
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,其中<<<HEAD是指主分支修改的内容,>>>>>fenzhi1 是指fenzhi1上修改的内容,
解决办法:
先将工作区的内容修改为master上的内容,并进行添加提交
bug分支问题:
在开发中,会经常碰到bug问题,那么有了bug就需要修复,在Git中,分支是很强大的,每个bug都可以通过一个临时分支来修复,修复完成后,合并分支,然后将临时的分支删除掉。
比如我在开发中接到一个404 bug时候,我们可以创建一个404分支来修复它,但是,当前的dev分支上的工作还没有完成,无法提交,比如我这个分支要2天完成,但是我issue-404 bug需要5个小时内完成。怎么办呢?还好,Git还提供了一个stash功能,可以把当前工作现场 ”隐藏起来”,等以后恢复现场后继续工作。如下:
现在我可以通过创建issue-404分支来修复bug了。
首先我们要确定在那个分支上修复bug,比如我现在是在主分支master上来修复的,现在我要在master分支上创建一个临时分支,
如上图,我们已经把issue-404解决了,并删除了该分支
现在,我们回到dev分支上干活了,工作区是干净的,那么我们工作现场去哪里呢?我们可以使用命令 git stash list来查看下。如下:
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,可以使用如下2个方法:
- git stash apply恢复,恢复后,stash内容并不删除,你需要使用命令git stash drop来删除。
- 另一种方式是使用git stash pop,恢复的同时把stash内容也删除了。
示例如下:
而后当我们把分支dev1的任务完成以后,进行添加操作以后,合并即可,如下图:
多人协作
当你从远程库克隆时候,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程库的默认名称是origin。
- 要查看远程库的信息 使用 git remote
- 要查看远程库的详细信息 使用 git remote –v
一:推送分支:
推送分支就是把该分支上所有本地提交到远程库中,推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
使用命令 git push origin master
比如我现在的码云上的test2.txt代码如下:
本地仓库test2.py代码如下:
现在我想把本地更新的readme.txt代码推送到远程库中,使用命令如下:
推送成功,码云上的test2.txt更新为:
可以看到 推送成功了,如果我们现在要推送到其他分支,比如dev分支上,我们还是那个命令 git push origin dev
那么一般情况下,那些分支要推送呢?
1.master分支是主分支,因此要时刻与远程同步。
2.一些修复bug分支不需要推送到远程去,可以先合并到主分支上,然后把主分支master推送到远程去
3.抓取分支
4.多人协作时,大家都会往master分支上推送各自的修改。现在我们可以模拟另外一个同事,可以在另一台电脑上(注意要把SSH key添加到github上)或者同一台电脑上另外一个目录克隆,新建一个目录名字叫testgit2
但是我首先要把dev分支也要推送到远程去,如下
接着进入git_test2目录,进行克隆远程的库到本地来,如下:
$ git clone https://gitee.com/mixtea/Gittest.git
现在我们的小伙伴要在dev分支上做开发,就必须把远程的origin的dev分支到本地来,于是可以使用命令创建本地dev分支:git checkout –b dev origin/dev
现在小伙伴们就可以在dev分支上做开发了,开发完成后把dev分支推送到远程库时
下面我们做一个在本地仓库分支中修改test1.txt内容后推送至远程的demo:
小伙伴们已经向origin/dev1分支上推送了提交,而我在我的目录文件下也对同样的文件同个地方作了修改,也试图推送到远程库时,如下会发生推送错误
如下图:
由上面可知:推送失败,因为我的小伙伴最新提交的和我试图推送的有冲突,解决的办法也很简单,上面已经提示我们,
先用git pull把最新的提交从origin/dev抓下来,然后在本地合并,解决冲突,再推送。
git pull 也失败了,原因是没有指定本地dev分支与远程origin/dev分支的链接,根据提示,设置dev和origin/dev的链接:如下:
指定本地dev分支与远程origin/dev分支的链接: git branch --set-upstream-to=origin/dev1 dev1
这回git pull成功,但是合并有冲突,需要手动解决,解决的方法和分支管理中的 解决冲突完全一样。解决后,提交,再push:
到码云上查看dev1上的推送状况,推送成功:
因此:多人协作工作模式一般是这样的:
- 首先,可以试图用git push origin branch-name推送自己的修改.
- 如果推送失败,则因为远程分支比你的本地更新早,需要先用git pull试图合并。
- 如果合并有冲突,则需要解决冲突,并在本地提交。再用git push origin branch-name推送。
Git基本常用命令如下
mkdir: XX (创建一个空目录 XX指目录名) pwd: 显示当前目录的路径。 git init 把当前的目录变成可以管理的git仓库,生成隐藏.git文件。 git add XX 把xx文件添加到暂存区去。 git commit –m “XX” 提交文件 –m 后面的是注释。 git status 查看仓库状态 git diff XX 查看XX文件修改了那些内容 git log 查看历史记录 git reset –hard HEAD^ 或者 git reset –hard HEAD~ 回退到上一个版本 (如果想回退到100个版本,使用git reset –hard HEAD~100 ) cat XX 查看XX文件内容 git reflog 查看历史记录的版本号id git checkout — XX 把XX文件在工作区的修改全部撤销。 git rm XX 删除XX文件 git remote add origin https://github.com/ev-power/XiaoYong 关联一个远程库 git push –u(第一次要用-u 以后不需要) origin master 把当前master分支推送到远程库 git clone https://github.com/ev-power/XiaoYong 从远程库中克隆 git checkout –b dev 创建dev分支 并切换到dev分支上 git branch 查看当前所有的分支 git checkout master 切换回master分支 git merge dev 在当前的分支上合并dev分支 git branch –d dev 删除dev分支 git branch name 创建分支 git stash 把当前的工作隐藏起来 等以后恢复现场后继续工作 git stash list 查看所有被隐藏的文件列表 git stash apply 恢复被隐藏的文件,但是内容不删除 git stash drop 删除文件 git stash pop 恢复文件的同时 也删除文件 git remote 查看远程库的信息 git remote –v 查看远程库的详细信息 git push origin master Git会把master分支推送到远程库对应的远程分支上
git branch --set-upstream-to=origin/dev1 dev1 指定本地dev分支与远程origin/dev分支的链接