Git
节点
Q:每次commit,Git储存的是全新的文件快照还是储存文件的变更部分?
A: 全新的文件快照
Git储存的是全新的文件快照,而不是文件的变更记录。也就是说,就算你只是在文件中添加一行,Git也会新建一个全新的blob object。那这样子是不是很浪费空间呢?
这其实是Git在空间和时间上的一个取舍,思考一下你要checkout一个commit,或对比两个commit之间的差异。如果Git储存的是问卷的变更部分,那么为了拿到一个commit的内容,Git都只能从第一个commit开始,然后一直计算变更,直到目标commit,这会花费很长时间。而相反,Git采用的储存全新文件快照的方法能使这个操作变得很快,直接从快照里面拿取内容就行了。
当然,在涉及网络传输或者Git仓库真的体积很大的时候,Git会有垃圾回收机制gc,不仅会清除无用的object,还会把已有的相似object打包压缩。
Merge 和 Rebase的区别
$ git pull --rebase
和$ git pull
区别git pull
是git fetch + git merge FETCH_HEAD
的缩写,所以默认情况下,git pull
就是先fetch,然后执行merge操作,如果加-rebase参数,就是使用git rebase代替git merge 。
现在有这样一个现实的请况,就是B同学准备进行第4次提交的时候,同学A在master主分支上进行了一次提交,master的提交已经向前走了
此时的git分支类图是这样的
此时我们知道B同学开发的dev分支是基于C2提交点切出来的,而这个时候master分支已经被更新了
如果B同学开发完毕,需要将其所作的功能合并到master分支 ,他可以有两种选择:
Merge
直接git merge,那么这个时候会这么做
(1)找到master和dev的共同祖先,即C2
(2)将dev的最新提交C5和master的最新提交即C6合并成一个新的提交C7,有冲突的话,解决冲突
(3)将C2之后的dev和master所有提交点,按照提交时间合并到master
Rebase
直接git rebase
切换分支到需要rebase的分支,这里是dev分支
执行git rebase master,有冲突就解决冲突,解决后直接git add . 再git rebase –continue即可
发现采用rebase的方式进行分支合并,整个master分支并没有多出一个新的commit,原来dev分支上的那几次(C3,C4,C5)commit记录在rebase之后其hash值发生了变化,不在是当初在dev分支上提交的时候的hash值了,但是提交的内容被全部复制保留了,并且整个master分支的commit记录呈线性记录
此时git的分支类图
小结
简单来讲:rebase会改变提交历史,但可以使分支干净,需要慎重。merge会新建节点,不改变提交,但是容易使分支变乱。
git merge 会让2个分支的提交按照提交时间进行排序,并且会把最新的2个commit合并成一个commit。最后的分支树呈现非线性的结构。(创建新的commit,节点hash不变)
git reabse 将dev的当前提交复制到master的最新提交之后,会形成一个线性的分支树。(无新建commit,发起rebase的分支非祖先节点往后的节点复制,hash值改变)
Pull 和 Fetch 的区别
git fetch
在拉取代码过程中,git fetch
会首先检查本地仓库和远程仓库的差异,检查哪些不存在于本地仓库,然后将这些变动的提交拉取到本地。
但是,这里请注意,它是把远程提交拉取到本地仓库,而不是本地工作目录,它不会自行将这些新数据合并到当前工作目录中,我们需要继续执行git merge
才会把这些变动合并到当前工作目录。
git pull
git pull
和git fetch
刚好相反,它直接获取远程的最新提交,直接拉取并合并到本地工作目录,而且在合并过程中不会经过我们的审查,如果不仔细检查,这样很容易遇到冲突。