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 pullgit fetch + git merge FETCH_HEAD的缩写,所以默认情况下,git pull就是先fetch,然后执行merge操作,如果加-rebase参数,就是使用git rebase代替git merge 。

现在有这样一个现实的请况,就是B同学准备进行第4次提交的时候,同学A在master主分支上进行了一次提交,master的提交已经向前走了

此时的git分支类图是这样的

未命名文件 (3).png

此时我们知道B同学开发的dev分支是基于C2提交点切出来的,而这个时候master分支已经被更新了

如果B同学开发完毕,需要将其所作的功能合并到master分支 ,他可以有两种选择:

Merge

直接git merge,那么这个时候会这么做

(1)找到master和dev的共同祖先,即C2

(2)将dev的最新提交C5和master的最新提交即C6合并成一个新的提交C7,有冲突的话,解决冲突

(3)将C2之后的dev和master所有提交点,按照提交时间合并到master

未命名文件 (4).png

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的分支类图

未命名文件 (5).png

小结

简单来讲: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 pullgit fetch刚好相反,它直接获取远程的最新提交,直接拉取并合并到本地工作目录,而且在合并过程中不会经过我们的审查,如果不仔细检查,这样很容易遇到冲突。

原理

img

img

Author

white crow

Posted on

2022-07-26

Updated on

2024-03-25

Licensed under