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