本文主要包括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 ;resetHEAD 和 分支指针的一起改
- 
checkout对工作目录是安全的;reset --hard会完全强制覆盖工作目录