1. Git简史
2002年,Linux社区免费使用BitKeeper软件对Linux系统代码进行版本控制
2005年,BitKeeper免费使用权被收回,Linus使用C语言开发了分布式版本控制系统Git
2008年,GitHub上线
2. Git安装
- 安装路径英文无空格
- 调整环境变量,建议选择use git from git bash only
- 本地库与远程库的连接方式,选择Open SSL库
3. Git结构
3.1 本地
工作区—-git add—->暂存区—-git commit—->本地库
git核心本质是一个键值对数据库,可以向改数据库插入任意类型的内容,他会返回一个键值,通过该值可以在任意时刻再次检索该内容
3.2 远程
局域网:GitLab服务器
外 网:GitHub(国外),码云(国内)
4. Git命令行操作
4.1 Linux基本操作
clear:清除屏幕
Ctrl + L:翻页
echo:往控制台输出信息 echo ‘test content’> test.txt
ll:将当前目录下的子文件&子目录平铺在控制台
find 目录名:将对应目录下的子文件&子孙目录平铺在控制台
find 目录名 -type f:将对应目录下的文件平铺在控制台
rm 文件名:删除文件
mv 源文件 重命名文件:重命名
cat 文件的url:查看对应文件的内容
vim 文件的url:
按 i 进入插入模式 进入文件的编辑
按 esc ,和 :键 进行命令的输入
q! 强制退出
wq 保存退出
set nu 设置行号
4.2 Git操作
4.2.1 本地库初始化
进入文件夹,右键 Git Bash Here
git init
注意:生成的.git目录中存放的是本地库相关文件,不要删除
.git目录下文件介绍
hooks 目录包含客户端或服务端的钩子脚本
info 包含一个全局性排除文件
logs 保存日志信息
objects 目录存储所有数据内容
refs 目录存储指向数据(分支)的提交对象的指针
config 文件包含项目特有的配置选项
description 用来显示对仓库的描述信息
HEAD 文件指示目前被检出的分支
index 文件保存暂存区信息
4.2.2 设置签名
- 项目(仓库)级别 仅在当前本地库有效
git config user.name glh # 设置用户名glh
git config user.email glh@qq.com # 设置用户邮箱
- 系统级别用户 仅在当前登录的操作系统用户有效
git config --global user.name glh # 设置用户名glh
git config --global user.email glh@qq.com # 设置用户邮箱
仅仅加了一个 —global
优先级别:项目级别 > 系统级别
信息保存位置:~/.gitconfig文件
这里设置的签名与登录远程库的账号密码没有关系
4.2.3 底层对象
git对象
echo 'hello' | git hash-object --stdin
# 这句命令返回一个hash值用来标识这句话,但是并没有写到数据库中
# 内容不一样,对应的hash值也不一样
echo 'hello' | git hash-object -w --stdin
# 这句命令返回一个hash值,并写入数据库中
find ./ -type f
# 查看所有文件
git cat-file -p hash
# 查看内容
git cat-file -t hash
# 查看git对象的类型,为 blob
git hash-object -w ./filename.txt
# 将新创建的文件添加到git数据库中,即生成一个git对象
实质上git对象是一个key:value 即 hash:value
在git对象中,文件名并未保存,只能通过hash
此时的操作只是针对本地数据库进行操作,不涉及暂存区
tree对象
树对象能够解决文件名的保存问题,也允许我们将多个文件组织到一起
git update-index --add --cacheinfo 100644 hash filename.txt
# 文件模式为100644表明这是一个普通文件
# 文件模式为100755表明这是一个可执行文件
# 文件模式为120000表明这是一个符号连接
# --add 该文件并没有在暂存区中,首次要加add
# --cacheinfo 要添加的文件在git数据库中,没有位于当前目录下
暂存区做一个快照生成一个对象放到git数据库中
-git write-tree
# 对象类型是一个树对象
# 树对象里面的内容是暂存区的快照(项目的快照)
# 暂存区中文件名字不变 如果改变文件的内容,就会重新生成一个hash
# 存在的问题
不知道hash值对应的是哪一个版本
不知道这个版本的一些基础信息
commit对象
提交对象完美的解决了上面的问题
本质就是给树对象做一层包裹,包含项目的基础信息
commit-tree 需要指定树hash 以及该提交的父提交对象
echo 'second commit' | git commit-tree tree-hash -p 父hash
真正代表一个项目的是一个提交对象(数据和基本信息),这是一个链式的
4.2.4 Git基本操作
状态查看
git status # 查看工作区,暂存区状态
git ls-files -s # 查看暂存区文件
添加
git add filename # 指定文件
git add ./ # 当前目录所有文件
# 将工作区文件添加到暂存区
# 实际上包含了两种底层命令
## git hash-object -w filename # 有多少文件被修改,就执行多少次
## git update-index ....
提交
git commit -m 'commit message' filename
# 将暂存区内容提交到本地库
git commit -a -m 'commit message' filename
# git自动将已经跟踪过的文件暂存起来一并提交
## 也执行了两个底层命令
## git write-tree ..
## git commit-tree ..
查看历史记录
git log
git reflog # 常用
git log --greph # 图形显示
git log --pretty=oneline # 漂亮一行显示
git log --oneline #简洁显示
# HEAD@{移动到当前版本需要多少步}
前进后退
- 基于索引值 推荐
git reset --hard hash(部分值就可)
- 使用 ^ 符号 只能后退
git reset --hard HEAD^
# 几个 ^ 表示退几步
- 使用 ~ 符号 只能后退
git reset --hard HEAD~n
# 表示后退几步
reset的三个参数比较
soft:
仅本地库移动HEAD指针
mixed:
在本地库移动HEAD指针
重置暂存区
hard:
在本地库移动HEAD指针
重置暂存区
重置工作区
删除文件并找回
前提:删除前,文件存在时的状态提交到了本地库
操作:git reset --hard [指针位置]
1. 删除操作已经提交到本地库:指针位置指向历史记录
2. 删除操作尚未提交到本地库:指针位置使用HEAD
比较文件差异
git diff filename
# 将工作区中的文件和暂存区进行比较
git diff [本地库中历史版本] filename
# 将工作区中的文件和本地库历史记录比较
# 不带文件名比较多个文件
4.3 分支管理
4.3.1 什么是分支
在版本控制过程中,使用多条线同时推进多个任务。
4.3.2 分支的好处
- 同时并行推进多个功能开发,提高开发效率
- 各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支造成影响,失败的分支删除重新开始即可。
4.3.3 分支操作
# 创建分支
git branch [分支名]
# 查看分支
git branch -v
# 切换分支
git checkout [分支名]
# 合并分支
# 1.切换到接受修改的分支(master)
git checkout master
# 2.执行merge命令
git merge hot_fix
# 解决冲突
1. 编辑文件,删除特殊符号
2. 把文件修改到满意的程度,保存退出
3. git add filename
4. git commit
5. Git 基本原理
5.1 哈希
哈希是一个系列的加密算法,各个不同的哈希算法虽然加密强度不同,但是有以下几个共同特点:
- 不管输入数据量的大小,同一个哈希算法,输出结果长度固定
- 哈希算法确定,输入数据确定,输出数据保证不变
- 哈希算法确定,输入数据有变化,输出数据一定有变化,而且通常变化很大
- 哈希算法不可逆
Git底层采用的是SHA-1算法,从根本上保证数据的完整性
5.2 Git保存版本的机制
集中式
以文件变更列表的方式存储信息,这类系统将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。优点在于节省空间,缺点在于版本切换,速度慢。
Git
Git把数据看作是小型文件系统的一组快照,每次提交更新时Git都会对当前的全部文件制作一个快照索引。为了高效,如果文件没有修改,Git不再重新存储该文件,而是只保留一个链接指向之前存储的文件。所以Git的工作方式可以称之为快照流。优点版本切换,分支切换,非常快。
6. GitHub
登录账号
创建远程仓库
创建远程库地址别名
git remote -v # 查看当前所有远程地址别名 git remote add [别名] [远程地址]
- 推送
git push [别名] [分支名]
- 克隆
git clone [远程地址] # 完整的把远程库下载到本地 # 创建orgin远程地址别名 # 初始化本地库
- 拉取
pull = fetch + merge git fetch [远程库地址别名] [远程分支名] git merge [远程库地址别名/远程分支名] git pull [远程库地址别名] [远程分支名]
解决冲突
- 如果不是基于GitHub远程库的最新版所做的修改,不能推送,必须先拉取。
- 拉取下来后如果进入冲突状态,则按照”分支冲突解决”操作解决即可。
跨团队协作
- Fork
- 本地修改,然后推送到远程
- Pull Request
- 对话
- 审核代码
- 合并代码
- 将远程库修改拉取到本地
- SSH登录
# 进入当前用户的家目录 cd ~ # 删除.ssh目录 rm -rvf .ssh # 运行命令生成.ssh密钥目录 ssh-keygen -t rsa -C 账户名(邮箱) # 进入.ssh目录查看文件列表 cd .ssh ls -lF # 查看id_rsa.pub文件内容 cat id_rsa.pub # 复制id_rsa.pub文件内容,登录GitHub,点击用户头像→Settings→SSH and GPG keys New SSH Key 输入复制的密钥信息 回到Git bash 创建远程地址别名 推送文件进行测试
- Tag标签
# 为了清晰的版本管理,公司一般不会直接使用commit提交 # 创建本地tag信息 git tag -a v1.0 -m'版本介绍' # 删除tag git tag -d v1.0 # 将本地tag信息推送到远程库 git push orgin --tags # 拉取到本地 git pull origin --tags # 切换tag git checkout v1.0 # 指定tag下载代码 git clone -b v1.0 地址
7. Git工作流
7.1 概念
在项目开发过程中使用Git的方式
7.2 分类
7.2.1 集中式工作流
像SVN一样,集中式工作流以中央仓库作为项目所有修改的单点实体。所有修改都提交到Master这个分支上。这种方式与SVN的主要区别就是开发人员有本地库。Git很多特性并没有用到。
7.2.2 GitFlow工作流
GitFlow工作流通过为功能开发、发布准备和维护设立了独立的分支,让发布迭代过程更流程。严格的分支模型也为大型项目提供了一些非常必要的结构。![](Git and GitHub.assets/image-20200706155532405.png)
- 主干分支 master
- 开发分支 develop
- bug修理分支 hotfix
- 预发布分支 release
- 功能分支 feature
7.2.3 Forking工作流
Forking工作流是在GitFlow基础上,充分利用了Git的Fork和pull request的功能以达到代码审核的目的,更适合安全可靠地管理大团队的开发者,而且能接受不信任贡献者的提交。
8.IDEA中使用Git
8.1 在idea中配置Git
选择file→settings打开设置窗口,找到version control下的Git选项,找到git的安装位置,并点击Test按钮。
8.2 开发中Git的常见操作
8.2.1 初始化并提交项目到远程仓库【项目leader操作】
在GitHub/码云中创建远程仓库
将maven工程交给Git管理
配置忽略文件
提交到本地仓库
推送到远程仓库
8.2.2 克隆远程仓库到本地【开发人员】
- 从远程仓库克隆
8.2.3 本地仓库常规操作【开发人员】
新增文件
在ssm_dao模块涨,新增一个GitMapper接口,新文件状态红色,未进入暂存区
加入git之后,红色变绿色,已经进入暂存区:编辑文件
在ssm_dao模块中,修改GitMapper接口,文件变蓝色
正常编辑的文件默认放在暂存区,不需要再添加到暂存区
- 重置文件到修改前
比如修订了某一文件,需要重置到修改文件之前的状态,选择文件,右键菜单:选择Git→rollback
重置后,文件颜色自动消失,说明已经重置到修改之前的状态。
提交到本地仓库
- 提交当前文件
- 提交当前文件
8.2.4 本地仓库推送push至远程仓库
推送前一定要先拉取远程仓库对应分支
如果有冲突,先解决冲突,并提交到本地仓库
- 推送当前分支到远程仓库
8.2.5 分支操作
创建分支
切换分支
书签表示当前分支执行合并操作,master合并dev
先切回master分支,然后合并