前言
由于之前公司用的是svn进行版本控制,而新公司又是使用git进行代码管理操作,所以在业余时间学习了git相关的操作。从底层出发,再结合公司同事给提出的建议,针对某些git操作有了深入的理解。所以本文分为两个部分,第一部分解释了git如何进行版本控制的底层原理,第二部分则是辅以具体的git操作加深原理的理解与运用。
第一部分:Git底层如何进行版本控制
我们可以选定一个目录进行初始化仓库,执行 git init
后,会在该目录下生成一个.git
目录,目录里包含的几乎所有的git操作,结构如下:
arduino
- config //项目特有的配置选项
- description //仓库描述信息,主要给gitweb等git托管系统使用
- HEAD //文件,记录目前正在使用的分支
- hooks/ // 目录,包含git的钩子脚本
- info/ // 目录,包含一个全局性排除文件, 用以放置那些不希望被记录在 .gitignore 文件中的忽略模式
- objects/ //目录,存储所有的数据内容,
- refs/ //目录,存储指向数据的提交对象指针
首先我们需要了解,在git的提交过程中会保存以下三种object:
- blob object(二进制对象)
- tree object(树对象)
- commit object(提交对象)
现在我们开始简述git提交文件到本地的流程:
-
当我们把修改的文件添加到staging area时,git会在objects目录下为每一个add的修改文件生成一个blob object。里面只包含了该文件的内容,不包含文件名。
-
当我们把暂存区的文件commit到本地仓库时,git会在objects目录下生成两个文件,一个是tree object,一个是commit object。 a) Tree object内容包含了之前提交过的所有二进制文件的hash值以及文件名称。
b) Commit object文件内容则包含了tree object文件的hash值以及提交者的信息和提交的注释信息。
-
在.git目录下的refs目录里的refs/heads/selected-branch文件则记录了所选分支最后一次commit的hash值。
-
最后在HEAD文件中,则给出了当前所选分支的快照保存路径。例如:refs/heads/master
综上,git对每次提交相当于存了个快照,我们可以用HEAD文件来记录当前分支在本地的最新提交信息,当切换分支时,HEAD中保存文件的路径也会随之改变,这就相当于指针的指向一般。当我们指向某一个提交的快照时,git会先去到objects中查找相应的commit的hash值,解析后找到存在其中的tree的hash值,最后再解析树文件内容,找到本次快照中所有文件的hash值,再索引到相应的文件进行解析输出。
第二部分:工作中会用到的Git相关操作
1.git rebase
提交的特性代码与主分支的代码存在冲突,这个时候可以使用merge与rebase来进行操作。
Merge操作:
会引入一个合并分支,然后再进行提交,历史记录不太好看,不够优雅
Rebase操作:
将我们的更新的节点拼接到主分支最新的更新节点上 ,对于项目的日益庞大,更容易溯源,查找缺陷。
Rebase进阶-交互式Rebase
上半部分是TODO list,可以通过改变前面的绿色字体进行命令修改。
- pick:调整pick顺序可以改变提交顺序
- squash:可以把多次提交整合成一次提交
1.顺序调整
修改pick的顺序即可实现
2. ###### Squash压缩指令
把其中一个pick改为squash则可以把多个合并在一起
3.Drop丢弃指令
可用于丢弃指定的版本更新,不合并在主分支上
2.Git cherry-pick
- 合并单个提交:应用某个分支上的一个提交到当前分支
- 修复BUG:在某个分支上的BUG被修复,并想应用到其他分支
- 提取特定功能:在一个分支上开发了新功能,并想运用到其他分支上
master上多个commit,怎么sqaush?
3.Git line ending(LF,CR,CRLF)
原因:不同平台或操作系统之间的换行符不一样。例如windows是CRLF(\r\n),而Unix和Mac则是LF(\n)。
LF和CRLF区别
LF: Line Feed换行
CR:回车
CRLF: Carriage Return Line Feed 回车换行
所以需要注意不同平台间协作的问题。
解决办法:
Windows设置:
arduino
git config --global core.autocrlf true
MacOS设置:
css
git config --global core.autocrlf input
Git移动都要基于HEAD
Git cherry-pick c1 c2 c5: 移动c1 c2 c5到当前选定分支
Git rebase -i HEAD~4 可以重置当前选定分支的顺序,选择哪些可以提交,可以不提交等
openssl -verify