作为一个工作两年的开发同学,git是每天都要接触的工具。但IDEA对git的封装已经满足了日常的代码提交需求,所以一直是以点点点的形式进行代码提交与更新,几乎没用命令行提交过(现在想来也是有些惭愧),对于git架构与底层也了解甚少。近期刚好研究代码相关,就趁此机会把git完整的学习一下。
1. 入门介绍
1.1 版本控制系统
git的本质是版本控制系统。版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。版本控制系统主要分为集中式、分布式,分别以svn、git为代表。
1.1.1 集中式版本控制系统 - CVCS
CVCS
有一个集中管理的服务器用来保存所有的修订版本,开发同学们通过客户端连接到服务器,获取最新的文件或更新文件。从图例中就可以看出CVCS的特点:单点、网络强依赖。
SVN
常见的subversion,现归属Apache,是代表性的集中式版本控制系统,除此之外还有TortoiseSVN。通常都是可爱的小乌龟图案。
1.1.2 分布式版本控制系统(DVCS)
DVCS
不再使用中央仓库, 取而代之的是本地仓库与远端仓库。本地仓库里包含了所有的版本历史,与本地仓库交互并不需要网络。
Git
大部分版本控制系统存储的是每个文件与初始版本的差异。但git与常见的版本控制系统并不同。git以快照的形式来进行不同版本的保存。提交更新或保存项目状态时,对当时的全部文件创建一个快照并保存这个快照的索引。如果文件没有修改只保留一个链接指向之前存储的文件。常见的有gitlab、github。
1.1.3 对比
集中式与分布式版本控制系统的最大区别在于,版本控制的位置在中央服务器还是本地电脑。
集中式
分布式
服务器故障时是否可提交
❌
✅
无网络也可工作
❌
✅
1.2 Git
1.2.1 结构
分支(Branch):一条独立的开发线,与与开发主线分离,可在不影响主线的同时工作。
工作区(Workspace):本地的代码区。
暂存区(Staging Area):临时存放代码的改动,即文件.git/index。
本地git仓库(Local Repository):存储于本地,含有所有版本的项目数据。
远程git仓库(Remote Repository):存储于远端,含有所有版本的项目数据。
1.2.2 特点
git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不只是一个简单的 VCS。
- 三种状态:commited(已提交)、modified(已修改)、staged(已暂存)
- 三个工作区:工作区、暂存区域、Git 仓库(远程&本地)
- 保证完整性:丢失信息后及时发现。通过SHA-1的哈希计算校验和,判断信息完整性
- 一般只添加数据:commit后,数据很难丢失
- 近乎所有操作都是本地执行: 速度极快,无需网络也可提交
2. 基础使用
2.1 提交流程
如果是研发人员,对git的提交绝对不陌生。在日常中使用git最高频的操作是将自己最新的修改推到远端分支,具体的操作流程如下:
- 在工作区中修改文件。
- 暂存文件,将文件的快照放入暂存区域。
- 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
2.2 使用方式
git主要两大使用方式:图形化页面、命令行。
2.2.1 图形化页面
在许多ide中都可以通过点击页面菜单的方式进行git commit、push等操作。如下图就是IDEA中的git操作菜单,可以看到已支持的命令可覆盖大部分的日常git使用需求,但依旧无法支持全部git指令。使用起来较为简便,只需要点点点即可。
2.2.2 命令行
在Terminal中直接手敲命令完成git交互。可执行全部git指令,根据所需自定义参数等。需要手动输入命令,但灵活性较高。
2.3 常用命令
总结了日常使用中最常用的六条命令如下。文章末尾也总结了git的大部分命令列表。
git add
增加git对指定文件的跟踪,将文件增加到暂存区
git pull
将远程仓库的代码拉到本地
git push
将代码从本地仓库上传到远程仓库
git clone
将一个远程仓库中的项目拷贝到本地
git commit
将所选暂存区的文件提交到本地仓库
git checkout
切换分支
3. 关键组件
3.1 文件
3.1.1 文件状态
一个文件在本地的状态变化主要有未跟踪、未修改、已修改、已暂存四种,会根据用户的操作不断变化。
3.1.2 忽略文件
在项目中有些文件无需纳入git管理,比如运行过程数据等。可记录在项目根目录的.gitignore中,去除git对该文件的管理。
GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,详见https://github.com/github/gitignore
3.2 标签
git支持打标签的方式来记录关键节点,可用于记录发布版本等。可以通过在特定的标签上创建一个新分支来复现打了标签的版本。
3.2.1 标签类型
轻量标签(lightweight):一个特定提交的引用。
附注标签(annotated):存储在 Git 数据库中的一个完整对象。通常创建的标签都是附注标签。
3.2.2 标签命令
标签列表
git tag
列出已有的标签
git show ${标签名}
某个标签信息与对应的提交信息
创建标签
git tag -a ${标签名} -m ${备注}
创建附注标签
git tag ${标签名}
创建轻量标签
git tag -a ${标签名} ${某个提交的校验和}
基于已有的提交创建标签
git push origin ${标签名}
将标签推到服务器上
恢复标签
git checkout -b ${分支名} ${标签名}
标签代码的恢复依赖于分支
3.3 分支
几乎所有的版本控制系统都以某种形式支持分支。分支可以把个人的开发工作从主线上分离,以免影响开发主线。 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费很多时间。git 的分支,其实本质上仅仅是指向提交对象的可变指针。做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
3.3.1 类型
master
主分支,代码的正式版本。原则上不能直接在master分支上修改,只能从其他分支合并。
其实master与其他分支并无不同,之所以用master做主分支,是因为git init默认创建的分支就是master,大家懒得改。
develop
主开发分支,包含要发到下一个release分支的代码。
feature
功能分支,主要用于开发新功能的分支。aone上新建变更后拉出的就是feature分支
release
预发布分支,在发布正式版本前,将待发布的分支都合并到release分支,打出一个预期发布版本。Aone上多分支发布的集成分支就是release分支。
hotfix
bug修复分支,做短小精悍的bug修复。
3.3.2 常用指令
git branch
创建新分支 ,相当于在当前所在的commit 上创建一个指针。Git 的分支实质上仅是包含所指对象校验和的文件,所以它的创建和销毁都异常高效。
git checkout
切换分支
3.3.3 HEAD指针
概念
HEAD指针总是通过分支指针,间接的指向当前分支的最新提交。
样例
文字可能不好理解,我们直接看git中的head指向就明白了。在命令行中进入某个项目的文件夹,目前处于master分支。进入.git文件夹,里面包含一个HEAD文件。
查看head文件内容,发现指向另一个文件 refs/heads/master
那么我们继续查看这个文件,发现是一串commit id
head所指向的commit id就是master最新一次提交的commit id
3.4 Commit
3.4.1 Commit的组成
blob:提交的文件,一个文件的一个版本对应一个blob对象
tree:目录,一个tree对象内部聚合了另一些tree或者blob
commit:一次提交.一个commit可以理解为某一个版本下的仓库的各个文件以及文件夹的快照。相当于聚合了这个版本下的blob以及tree对象。commit同时也会包含提交信息以及parent的commit。
3.5 协议
在clone项目时,有两种方式:SSH、HTTPS。
3.5.1 SSH
安全性较高,需要生成SSH密钥,并将本地公钥上传至gitlab。
3.5.2 HTTPS
安全性较弱,使用用户名与密码登录。
4. 展开说说
4.1 别名的使用
可以对一些常用指令设置别名,减少每次的打字数
比如git commit,我想自定义成git ci,可设置git别名
git config --global alias.ci commit
后续commit只需要输入git ci即可。
4.2 git到底怎么读
这可以说是一个很有趣的话题了,作为一个"交友网站",读法还是十分多样的,大概如下:
- [git]
- [dʒit]
- [geit]
具体怎么读,并没有标准答案,目前博主读的是[git],参照Linus的读法。原视频
5. 命令汇总
常用指令
git clone
将一个远程仓库中的项目拷贝到本地
git add
增加git对指定文件的跟踪,将文件增加到暂存区
git commit
将所选暂存区的文件提交到本地仓库
git push
将代码从本地仓库上传到远程仓库
git pull
将远程仓库的代码拉到本地
git checkout
切换分支
分支
git branch
创建新分支
git log
按提交时间列出分支上的所有的更新
git reset
撤销操作,将head回退至指定状态
git merge
分支合并
git diff
工作目录中当前文件和暂存区域快照之间的差异
标签
**git tag **
列出已有的标签
git show ${标签名}
某个标签信息与对应的提交信息
**git tag -a ${标签名} -m ${备注} **
创建附注标签
git tag ${标签名}
创建轻量标签
git tag -a ${标签名} ${校验和}
基于已有的提交创建标签
git push origin ${标签名}
将标签推到服务器上
git checkout -b ${分支} ${标签}
将标签记录的阶段代码恢复到分支上
仓库
git init
初始化仓库
git config --list
列出所有 Git 当时能找到的配置。
**git status **
查看文件所处状态
git ls-remote (remote)
远程引用的完整列表
git fetch
拉取最新的远程仓库分支,本地仓库不变
附
Pro Git 中文版(第二版)
版权归原作者 宇宙超级无敌程序媛 所有, 如有侵权,请联系我们删除。