本文主要包括Git的用法加底层
使用
初始化相关
# --system 操作系统级别; --global 用户级别; 不加: 项目级别 |
文件相关
# 添加新文件(由未跟踪到跟踪状态,同时也是暂存状态)或者添加修改文件(由修改状态到暂存状态)(粗略这样说,其实底层做了更多事) |
分支相关
# 创建分支 |
stash相关
# 有时想切分支,但又不想提交,可以用到 stash 功能,是一种暂存的栈。这个栈是针对分支的~ |
回退相关
# 撤回工作目录的修改(未add -> 未修改) |
标签相关
# 列出所有tag |
远程相关
# 查看全部远程分支 |
看起来比较复杂,但只要记住一个逻辑链就好,也就是按以下3步走:
-
建立远程跟踪分支
git clone https://xxxx.git
git push orgin branchName
推新分支到远程git fetch orgin
拉远程的新分支
-
本地分支关联远程跟踪分支
git checkout branchName
创建本地新分支(和远程分支同名) 并关联 (还是它简单)git branch -u orgin/branchName
当前分支 关联git branch --track orgin/branchName
创建本地新分支 关联
-
愉快使用
git pull
拉到本地git push
推到远程(先 pull,解决冲突再 push)
上面是自己团队的项目(有权限),当想为开源项目做贡献(没权限)时,使用 pull request, 大致流程(用到再研究)为:
-
folk 一份
-
在 folk 的库中,作出改动并提交,注意提交前先拉远程库,保持最新。
-
进网站(如github),点 pullRequest
底层
git 的底层数据结构是一种在 object
目录中存放的 k-v 类型的数据。key 是 hash值 (前两位是子文件夹名,后面是文件名),value 是 数据内容。
数据内容 分为 git 对象(blob
)、树对象(tree
)、提交对象(commit
)
git 对象
代表文件,它是真正存数据的。它是一对一的(注意:一个文件的历史文件都算一个单独的文件)。
# 向数据库中写数据,并返回hash键值。存的是一个blob对象 |
树对象
代表版本,可以理解成一个树对象指向多个 git 对象,形成一个版本。
# 暂存区 写入 test.txt 的首个版本(指针信息) |
提交对象
相当于对版本添加描述信息。一个提交对象封装一个树对象,而且它是链式的,里面指向上一个提交对象。
# 生成提交对象,后接树对象hash值 |
文件相关
-
git add test.txt
相当于先将文件做成git对象
存入object
,再将它(指针信息)放入暂存区,等待提交。该操作是绝对安全的,因为数据已经写入文件中。所以可以理解为啥只有git add
,而没有什么git change
之类的,因为修改也会加git对象
。 -
git commit -m "xx"
由暂存区生成树对象,再生成提交对象。注意暂存区的东西不删除 -
git rm test.txt
相当于将该文件对应的(指针信息)从暂存区中删除,同时删除工作目录中的文件
分支相关
分支切换会切换工作目录,所以切换前,先把当前分支该提交的提交了,保证工作目录干净。
-
2个重要的东西:
refs
存放各个分支(和tags)的提交对象的指针(hashkey)HEAD
指明当前分支的指针位置
-
git branch branchname
相当于在refs/heads
目录中新建以分支名命名的当前分支的提交对象的指针 -
git checkout branchname
更改HEAD
文件;切换工作目录;影响暂存区 -
git commit -m "commit message"
更新refs
中对应分支的提交对象
回退相关
git checkout branchName
和 git reset --hard commitHash
的区别 :
-
checkout
只改HEAD ;reset
HEAD 和 分支指针的一起改 -
checkout
对工作目录是安全的;reset --hard
会完全强制覆盖工作目录