Git版本控制
文章目录
- Git版本控制
- 1. 版本控制
- 1.1 概述
- 1.2 版本控制优点
- 1.3 本地版本控制系统(离线版)
- 1.4 集中化的版本控制系统(联网版)
- 1.5 分布式版本控制系统(离线+联网版)
- 2. Git概述
- 2.1 Git基本工作流程
- 2.2 Git下载
- 2.3 windows下安装git
- 3. Git远程仓库托管
- 4. Git常用命令
- 4.1 初始化环境
- 4.2 创建本地仓库
- 4.3 从远程仓库clone
- 4.3.1 从码云克隆到/GitRepository下
- 4.3.2 从码云克隆其他开放的工程
- 4.4 工作目录、暂存区及版本库
- 4.5 文件四种状态及相互转换
- 4.6 文件的删除与回复
- 4.7 操作远程仓库
- 4.7.1 查看远程仓库
- 4.7.2 拉取、抓取和推送
- 1. fetch抓取
- 2. pull拉取(fetch+merge)
- 3. push推送到远程仓库
- 5. Git分支
- 5.1 分支概述
- 5.2 查看分支
- 5.3 创建、切换、推动本地分支
- 5.4 合并分支与解决冲突
- 5.4.1 合并分支
- 5.4.2 产生合并冲突
- 5.4.3 解决合并冲突
- 6.IDEA中使用Git
- 6.1 IDEA中配置Git
- 6.2 IDEA中工程创建、添加、提交、推送
- 6.3 IDEA克隆远程仓库
- 6.4 IDEA从远程仓库拉取
- 6.5 IDEA中版本对比与还原指定版本
- 6.6 IDEA中创建与切换分支
- 6.7 IDEA中合并分支与解决冲突
1. 版本控制
1.1 概述
版本控制是一种记录一个或若干个文件内容变化,方便将来查看版本修订情况(一个或若干个文件的历史修改记录)的系统,简称VCS(Version Control System)
示例:
1.要开发一个项目
a.刚开始搭建一个项目 v1.0
b.不断扩展业务,添加业务查询 v1.1
c.修复原有项目的bug v1.2
…不使用版本控制系统:可能无法还原到之前开发版本
使用版本控制系统:只要修改项目中任意一个文件,都会被VCS记录
2.浏览器历史记录
1.2 版本控制优点
- 使用版本控制可以方便记录文件的修改版本
- 回溯到任一历史状态
- 方便查看文件的修改细节,定位具体修改位置
- 即使文件被删除,也可以恢复到原始状态
1.3 本地版本控制系统(离线版)
1.4 集中化的版本控制系统(联网版)
本地化的版本控制系统管理对本地文件版本控制比较方便,但是如果是多个不同系统上的开发者操作同样文件就很难进行版本控制,因此衍生出了CVCS(Centralized Version Control Systems):通过一个单一的服务器来统一管理,这个服务器上保存所有文件的修改记录,使不同的开发者都可以获取最新的文件或提交修改,例如:SVN
1.5 分布式版本控制系统(离线+联网版)
对于CVCS,由于所有文件历史记录都在中央服务器保存一旦中央服务器出现故障而又没有备份,那么所有的开发者都无法使用版本控制,就可能出现丢失历史记录的风险,因此需要分布式版本控制系统DVCS(Distributed Version Control):开发者(客户端)不只获取最新的文件,而且还把整个代码仓库以及历史记录完整存储到本地,即使服务器出现故障,也可以从本地恢复,例如:Git
2. Git概述
自2002年开始,林纳斯·托瓦兹决定使用BitKeeper作为Linux内核主要的版本控制系统用以维护代码。因为BitKeeper为专有软件,这个决定在社群中长期遭受质疑。在Linux社群中,特别是理查德·斯托曼与自由软件基金会的成员,主张应该使用开放源代码的软件来作为Linux内核的版本控制系统。林纳斯·托瓦兹曾考虑过采用现成软件作为版本控制系统(例如Monotone),但这些软件都存在一些问题,特别是性能不佳。现成的方案,如CVS的架构,受到林纳斯·托瓦兹的批评。
2005年,安德鲁·垂鸠写了一个简单程序,可以连接BitKeeper的存储库,BitKeeper著作权拥有者拉里·麦沃伊认为安德鲁·垂鸠对BitKeeper内部使用的协议进行逆向工程,决定收回无偿使用BitKeeper的许可。Linux内核开发团队与BitMover公司进行磋商,但无法解决他们之间的歧见。林纳斯·托瓦兹决定自行开发版本控制系统替代BitKeeper,以十天的时间编写出git第一个版本。
Git是用于Linux内核开发的版本控制工具。与CVS、Subversion一类的集中式版本控制工具不同,它采用了分布式版本库的作法,不需要服务器端软件,就可以运作版本控制,使得源代码的发布和交流极其方便。git的速度很快,这对于诸如Linux内核这样的大项目来说自然很重要。git最为出色的是它的合并追踪(merge tracing)能力。
2.1 Git基本工作流程
- 从远程仓库中克隆代码到本地仓库
- 从本地仓库中checkout代码然后进行代码修改
- 在提交前先将代码提交到暂存区
- 提交到本地仓库。本地仓库中保存修改的各个历史版本
- 修改完成后,需要和团队成员共享代码时,将代码push到远程仓库
2.2 Git下载
Git有不同平台的版本,我们主要以常用的windows版本讲解
Git
Git - Reference
虽然有各种平台,但是都是通过git命令实现版本控制,即使有图形化界面版,底层本质上封装的依然是git命令,所以重点熟悉git常用的一些命令
2.3 windows下安装git
Standalone Installer:是一个安装应用程序,类似于安装微信、QQ等应用一样进行安装
Portable:绿色版,是一个压缩包。下载完成之后,将压缩包解压到什么位置,就安装在什么位置
我们直接下载Portable,选择好目录之后进行解压,完整的解压目录如下:
如果想要直接在Windows下的cmd命令行窗口进行查看,则需要添加环境变量
3. Git远程仓库托管
如何搭建Git远程仓库呢?我们可以借助互联网上提供的一些代码托管服务来实现,其中比较常用的有GitHub、码云(gitee)、GitLab等。
GitHub是一个面向开源及私有软件项目的托管平台,该平台只使用了Git进行版本控制,所以叫github
码云是国内的一个代码托管平台,由于服务器在国内,所以相比于GitHub,从码云克隆代码的速度更快
我们这里为了方便大家使用选用码云,码云和github操作差不多
- 注册码云,就像普通网站注册一样,不再赘述
- 创建公有仓库
红色*为必填内容
4. Git常用命令
4.1 初始化环境
# 用户信息配置,git每次提交都会使用这个配置信息
git config --global user.name satellite
git config --global user.email 2602105758@qq.com
# 查看配置信息
git config --list
配置信息可自行填写
4.2 创建本地仓库
# 创建myrepo文件夹,作为仓库
mkdir myrepo
cd myrepo
# 使用git命令初始化本地仓库,初始化成功后,myrepo下会有一个.git的隐藏文件夹
git init
4.3 从远程仓库clone
4.3.1 从码云克隆到/GitRepository下
cd E:\software\GitRepository
e:
# git clone命令
# 其实就是联网下载,将远程仓库克隆到本地成为本地仓库
# 仓库名作为根目录,根目录中会生成.git隐藏文件夹
git clone https://gitee.com/chaoshiahn/my-git.git
克隆完成
4.3.2 从码云克隆其他开放的工程
例如选择hutool,java常用工具包
git clone https://gitee.com/dromara/hutool.git
克隆完成
以上操作,必须处于联网状态!
从github上克隆项目是相同的命令及操作,但是克隆快慢取决于网速
4.4 工作目录、暂存区及版本库
- 工作目录(工作区,workspace):包含.git文件夹的目录就是工作目录,一般就是工程目录
- 版本库(version database):名叫.git的目录,保存提交的数据,元素数据,日志等信息
- 暂存区(stage/索引):是一个文件,保存下次将要提交的文件列表信息
4.5 文件四种状态及相互转换
Untracked(未跟踪):
此文件在工作区中, 但并没有加入到git库, 不参与版本控制. 例如:新建的文件
Unmodify(未修改):
文件已经入库, 未修改, 即版本库中的文件内容与工作区中文件完全一致. 例如:刚克隆下来的文件 README.md
Modified(已修改):
文件已修改, 仅仅是修改, 并没有进行其他的操作 例如:修改README.md的内容
Staged(暂存):
修改完文件,我们执行git add,这个时候文件就变为已暂存状态
# 查看仓库的状态
git status
在my-git文件夹下新建一个1.txt,然后在该目录下再次使用git status
命令
编辑README.MD,任意修改一下,保存,再次使用git status
命令查看
# 简洁输出
git status -s
# 将1.txt加入暂存区,此时1.txt由未跟踪状态转换成暂存状态
git add 1.txt
# 如果后悔了,将1.txt再由暂存状态还原为未跟踪状态
git restore --staged 1.txt
git status
# 重新将1.txt加入暂存区,此时1.txt由未跟踪状态转换成暂存状态
git add 1.txt
# 提交1.txt到本地仓库
git commit -m "commit 1.txt" 1.txt
git status
# 查看历史提交记录
git log
# 提交已修改的README.md,需要先把README加入暂存区,然后才能提交
git add README.md
# 如果不加-m参数,那么会默认打开编辑器;需要写入提交信息,保存即可
git commit README.md
# 查看提交的历史记录
git log
4.6 文件的删除与回复
# 删除工作区的1.txt
git rm 1.txt
git status
第一种恢复方式:
# 从暂存区中恢复1.txt
git restore --staged 1.txt
git restore 1.txt
第二种恢复方式:
#进入到暂存区
git rm 1.txt
#提交修改,清空暂存区中的1.txt
git commit -m "删除1.txt" 1.txt
#如果这个这个删除已经从暂存区提交到版本库
#考虑从提交历史记录中恢复1.txt
#查看提交记录
git log
#撤销之前的add,commit操作,恢复到暂存区
git reset 67a9
#从暂存区恢复1.txt
git restore 1.txt
4.7 操作远程仓库
4.7.1 查看远程仓库
如果想查看远程仓库服务器,可以运行 git remote
命令。 它会列出指定的每一个远程服务器的简写。 如果已经关联了远程仓库,那么可以看到一个 origin名字 ,这是 Git 克隆的仓库服务器的默认名字
#查看关联的远程仓库的名字
git remote
#查看具体的远程仓库地址
git remote -v
#本地仓库没有关联远程仓库
cd myrepo
git remote
git remote -v
4.7.2 拉取、抓取和推送
1. fetch抓取
#建立一个工作区文件夹
mkdir HelloGit02
#初始化本地仓库
cd HelloGit02/
git init
#建立本地仓库和远程仓库的连接
git remote add origin https://gitee.com/chaoshiahn/hello-git02.git
git remote -v
#从origin/master分支中抓取内容到版本库,不会merge到工作区
git fetch origin master
#将抓取的内容合并到工作空间
git merge origin/master
2. pull拉取(fetch+merge)
#从硬盘上删除HelloGit02
#建立一个工作区文件夹
mkdir HelloGit02
#初始化仓库
cd HelloGit02/
git init
#建立本地仓库和远程仓库的连接
git remote add origin https://gitee.com/chaoshiahn/hello-git02.git
git remote -v
#直接拉取到工作区
git pull origin master
3. push推送到远程仓库
我们以推送一个maven工程为例,它的流程是先从工作区—提交—>本地仓库—推送–>远程仓库
由于我们并不想把maven工程中所有的文件都推送,例如 .class文件,测试文件,日志等,只是想推送.java和配置文件,如果一个个挑选提交,然后推送,太过于繁琐,我们考虑让Git帮我们自动筛选,需要忽略文件或目录的规则
我们需要在工作区下新建一个**.gitignore的文件 ,在.gitignore**中书写忽略规则,常用规则如下:
# 忽略所有的 .a 文件
*.a
# 但跟踪多有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 之忽略当前目录下的TODO文件,而不忽略 subdir/TODO、
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
- maven工程使用的.gitignore规则
#在工作区目录下新建.gitignore文件
#忽略target目录
target/
#忽略test目录
test/
#忽略日志文件
*.log
- 初始化想要push的项目project 并简历.gitignore
# path为project目录
cd path
#初始化本地仓库
git init
#新建.gitignore 写入以下内容
target/
test/
*.log
#将所有源码等文件添加到暂存区
git add .
#查看暂存区文件
git ls-files
#提交到本地仓库
git commit -m "第一次提交project工程" .
#查看提交记录
git log
# 关联远程仓库
git remote add origin https://gitee.com/chaoshiahn/ssm-curd.git
git remote -v
#推送到远程仓库
#在push的时候需要输入码云的账号和密码 或者 需要修改windows凭据
#-f 强制推送,如果不加,那么会要求先pull拉取远程仓库的代码与本地代码合并,再push
git push origin master -f
5. Git分支
5.1 分支概述
在对版本库进行最初的提交后,Git会默认建立一个名为master的分支。之后的提交在切换分支之前都会增加在master分支里
master:正式发布的代码-稳定版
|-- dev:开发版(开发新的模块)
|-- fix-bug:修复bug
为了让仓库群组的成员的开发相互之间不受影响,可以在主要分支基础上建立自己专用的分支。完成开发的成员们,将自己分支的修改导入到主要分支,这样大家都可以不受其他成员的影响,导入自己的修改内容。而且每个提交的历史记录都会被储存,当发生问题时,可以更容易找到发生问题的地方
5.2 查看分支
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 本地分支 + 远程分支
git branch -a
5.3 创建、切换、推动本地分支
#创建dev分支
#如果当前指向master分支,那么创建的dev分支会拷贝master分支下所有的内容
git branch dev
#查看本地分支
git branch
#切换到dev分支
git checkout dev
#将dev推送到origin远程仓库
git push origin dev
dev中的文件和master中的文件刚开始是完全相同的,因为就是在master分支的基础上衍生出来的,但是随着开发的推进,例如我在dev上开发未上线的功能,master只放发布功能,那么两者代码就开始产生不同
5.4 合并分支与解决冲突
5.4.1 合并分支
#切换到dev分支
git checkout dev
#在dev分支中的day02-maven-ssm的src/main/java下添加一个Person.java
public class Person{
}
#添加到暂存区然后提交到dev分支下
git add src/main/java/Person.java
git commit -m "添加 Person.java" src/main/java/Person.java
#切换到master分支,此时master分支下并没有Person.java
git checkout master
#将dev分支合并到master分支
#合并后master分支中也有dev新加的文件
git merge -m "第一次将dev分支内容合并到master分支" dev
5.4.2 产生合并冲突
如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git就无法合并它们,因为Git不知道你是要将两者内容合并还是其中一个覆盖另一个等操作,所以Git会产生冲突,这个冲突需要我们手动解决
#切换到master分支,修改Person.java
git checkout master
#修改Person.java为以下代码
public class Person{
private String name;//master分支添加的属性
}
#提交master分支
#对于修改后的文件可以直接commit,当然也可以先add再commit
git commit -m "master分支修改Person.java" src/main/java/Person.java
#切换到dev分支,修改Person.java
git checkout dev
#修改Person.java为以下代码
public class Person{
private int age;//dev分支添加的属性
}
#提交到dev分支
git commit -m "dev分支修改Person.java" src/main/java/Person.java
#切换到master分支
git checkout master
#将dev分支合并到master上
#此时就会产生冲突
git merge -m "将dev分支合并到master分支" dev
5.4.3 解决合并冲突
#在master分支上修改冲突文件
#这里我们修改为合并两个属性,当然也可以删除某个属性,完全取决开发者需求
public class Person{
private String name;//master分支添加的属性
private int age;//dev添加的属性
}
#重新提交
#此时后面不能带Person.java,这里要提交所有修改
git add src/main/java/Person.java
git commit -m "解决了合并冲突"
重新推动master和dev分支
# 推送本地所有分支(master,dev到origin远程仓库)
git push origin --all
6.IDEA中使用Git
6.1 IDEA中配置Git
由于我们要在windows下的IDEA中使用git,所以需要下载git的windows版,然后指定git.exe的路径,测试成功即可
6.2 IDEA中工程创建、添加、提交、推送
- 创建一个maven工程,启用git进行版本控制
启用后,相当于执行git init
指令,在工程根目录生成 .git 隐藏文件
- 提交GitDemo工程
Ctrl + K
提交,提交后可以在log界面(git log
)看到提交历史记录
- 推送到远程仓库
新建仓库
IDEA中操作
6.3 IDEA克隆远程仓库
6.4 IDEA从远程仓库拉取
- 在远程仓库的src/main/java/edu/com下新建Person.java,并提交
- 本地仓库已经不是最新版本,因此做pull动作,从远程仓库拉取最新内容
6.5 IDEA中版本对比与还原指定版本
- 如果我们修改git-demo中的Person.java,添加了address属性,并提交
- 将当前版本的Person.java与之前版本的Person.java做比较
- 此时要是后悔了,想要还原到之前的版本
soft:完全保留工作区和暂存区,会撤销git commit提交,保留git add操作
mixed:完全保留工作区,会撤销commit提交和 git add操作
hard:工作区恢复到所选的commit的状态 , 之后的commit和改动全部丢弃
keep:keep 类似于 hard,但如果在工作目录中有未提交的改动,keep会保留这些改动,而 hard会丢弃这些改动
6.6 IDEA中创建与切换分支
创建
切换
6.7 IDEA中合并分支与解决冲突
以下master分支和dev分支均基于原始的Person.java进行操作
- 切换到master分支,然后删除Person.java的height属性并提交
- 切换到dev分支,然后在Person.java添加city属性并提交
- 切换到master分支,将dev分支合并到master分支
由于我在master分支和dev分支修改了同一个Person.java,,合并时会产生冲突,此时我们解决冲突,同时保留address和height属性