Git使用上手
一、起步
1.1 安装
Windows、Linux请自行前往官网,按照说明完成
这里说一下Mac版本,分两种情况:
- 使用Apple提供的git发行版:这种情况使用的是Xcode内的
Command Line Tools
- 使用homebrew安装,强烈建议.因为Xcode内的git工具不太完整,缺少
gitk
、HTML格式的文档等
1.2 最小化配置
配置user.name和user.email
1 | git config --global user.name 'your_name' |
1.2.1 config的三个作用域
1 | git config --local # 只针对某仓库 |
显示config的配置,加--list
1 | git config --list --local |
1.3 使用本地HTML文档
1 | 例如查看git log命令的使用文档 |
二、建一个Git仓库
2.1 初始化
此时存在两种场景:
- 项目代码已经存在,要把项目加入Git版本控制
- 新建一个项目并使用Git来管理
针对第一种情况,我们使用如下命令:
1 | cd 项目代码所在的文件夹 |
针对第二种情况,则是使用如下命令:
1 | cd 某个文件夹 |
2.2 将文件加入Git版本控制
1 | git add 文件名 # 如果不将文件纳入版本控制,后续操作则会报错 |
然后查看一下当前的状态:
1 | git status # 可查看当前git项目的状态,如哪些文件被修改,而哪些文件未被版本管理 |
此时的文件,是存在于临时的缓存(暂存区)当中,要真正提交还需要执行以下命令:
1 | git commit -m "变更说明" |
这样我们就真正的将一个文件提交进版本了,我们还可以看一下当前的日志:
1 | git log |
2.2.1 新建和切换分支
1 | git checkout -b 分支名 |
2.3 回退修改
1 | git reset --hard # 彻底回退,暂存区和所有未提交的变更记录都会被清理 |
2.4 文件重命名
1 | git mv 文件原名 文件现名 |
2.5 比较版本的差异
我们可以先查看一下历史:
1 | git log --oneline |
1 | git diff 7499e49 5f06285 |
如果是使用当前版本进行比较,我们可以使用HEAD来指代:
1 | git diff 5f06285 HEAD |
2.6 删除分支
1 | git branch -d <BranchName> |
三、工作区与暂存区的认识
在Git
当中,如果仅对文件作了add
,但没有执行commit
的话,文件会被存储进暂存区,而我们对文件进行创作修改的区域被称为工作区
当我们将文件提交进暂存区后,依然可以在工作区继续修改我们的文件,而此时暂存区内的文件是独立于工作区的
这也就意味着,我们随时可以用暂存区内的版本覆盖工作区(如对工作区的修改不满意),而又不需要提交到版本控制,这在实践当中非常实用
补充:
1 | git add -u # 将项目中所有工作区的文件一起提交到暂存区,而不需要一个个写文件名 |
四、图形化工具的介绍
直接在命令行输入gitk
即可.
在MacOS上,如果使用的是Xcode提供的git是没有gitk
工具的,需要使用brew安装一下
同时如果使用的是MacOS的暗主题,gitk
的菜单栏上的文字会因为和底色相同的原因看不见,需要将鼠标移上去
五、了解.git目录
5.1 HEAD文件
首先,我们进入.git
目录,尝试查看一下HEAD
文件的内容:
1 | cat HEAD |
我们会发现HEAD
文件其实是一个引用,而且指向的位置和当前工作的分支有关,如当前工作分支为master
而假设我们当前切换分支到了test
,那么此时HEAD文件就会指向test
分支
5.2 config文件
该文件下除了保存了该仓库下的核心配置之外,如果设置了仓库级别的用户配置,也会写入该文件
例如:
1 | git config --local user.username "test" # 修改当前仓库的用户名 |
该文件内的内容则会变为:
1 | [core] |
5.3 refs目录
在refs目录中,存在两个子目录:
- heads:里面有各个分支的子文件
- tags:里面有各个标签(可看作是里程碑)的子文件
先看heads目录,我们先查看一下master文件的内容:
1 | cat master |
我们还可以查看该文件是什么类型的:
1 | git cat-file -t master # -t参数可以查看类型 |
同样的,在tag目录下的文件里面存放的也是hash值,文件类型属于tag
通过以下命令可以查看该tag
是存放的哪一个commit
对象:
1 | git cat-file -p tag名或tag的hash # -p参数可以查看内容 |
5.4 objects目录
我们进入objects目录后,会看到很多两个字符组成的文件夹,以及pack(打包目录)
例如:
1 | ls -la |
我们随便挑选一个两个字符的目录进去,会发现内部文件是这样的:
1 | cd 06 |
此时我们可以使用命令查看一下该对象的类型:
1 | 注意:此处的hash为[两位长度的目录名 + 目录内文件名] |
tree
即目录类型
然后,我们可以查看该对象的内容,使用以下命令(参数: -p):
1 | git cat-file -p 060fede4878a49e95fc444e9a243fa77edc710f4 |
blob
即是文件对象类型
我们可以进一步查看该blob
类型:
1 | git cat-file -t 827ae020300b109c1e0e7ee58891e592d85df66c # 查看类型 |
至此,我们已经接触了git的如下几种类型:
- commit
- tag
- tree
- blob
提示: 在git
中,只要两个文件内容相同,那么对于git就是唯一的一个blob
5.4.1 commit、tree、blob三者的关系
我们可以通过git log
命令查询到每一次的commit的hash,如果我们查询某次commit的内容:
1 | git cat-file -p 7499e499b62642764e31475f # hash不需要输入完整,只要能让git唯一找到目标就可以 |
我们会发现,commit对象中永远存储了一个tree,该tree代表截止该的commit为止,此git项目的所有内容,我们可以继续查看该tree的内容:
1 | git cat-file -p 3d5799c550fa4b815545f02 |
也就是说,此commit提交后,我们的git项目中仅有一个文件,因此显示为一个blob
对象;如果此时还有子目录的话,会显示为一个tree
对象
这就是三种对象的关系
六、使用分离头指针
现在假设有这样一个场景,我们要基于master的倒数第二个commit来创建一个分支,由于我们并不是基于最新的commit,所以要先把分支切换到commit上,而不是branch上,这就是分离头指针
不过千万要谨慎操作,因为分离后的branch是没有名字的,如果不赋予名字,后面会导致修改丢失.
示例如下:
1 | 切换到一个commit上,而不是branch,从而实现分离头指针 |
然后我们查看一下当前branch的情况:
1 | git branch |
现在让我们来创建一个分离后的文件吧:
1 | echo "我是分离头指针版本独有的文件内容" > 分离头指针.txt |
此时我们的新分支是没有名字的,如果我们切换到其他分支,有可能会导致该分支上的修改失效
这里我们尝试切换到master分支:
1 | git checkout master |
所以这里我们按照提示,给没有名字的新分支一个名字:
1 | git branch 实验分离头指针分支 718daed |
然后我们来一起看一下当前的log:
1 | git log --all --graph |
由此可见,我们顺利得在master之前的版本上创建了分支