赞
踩
目录
这一篇其实不属于计算机基础的,但是随着大家平时工作还有开源一些项目的版本控制的使用,使用叫多的git。
回过头来,有时在思考reverse和rebase区别,回归到底层的一些原理的时候,就有茅塞顿开的感觉了。
首先Git有分三个区,工作区,暂存区和版本库。
Git当中一共有3种主要的对象:blob,tree,commit
git add 多一个blob文件,repository的一个文件,内容为文件内容
git add 再多一个blob文件
git commit后 会有两个tree 一个commit
tree,存储blob对象和子tree对象,这类型的对象在Git里面代表的就是一个文件夹,而这个对象的内容就是面向它所包含的文件夹和文件的指针。
commit对象,包含了一个面向根目录tree对象的指针,而且还包含了committer的个人信息还有commit的注释。
三个对象之间关系。总结就是
commit 指向 tree 指向 tree 或者 blob
查看对象内容可以参考官方文档,Git - git-cat-file Documentation
git cat-file --batch-check --batch-all-objects
the SHA-1, type, and size of each object is printed on stdout
sha1跟md5类似是一个摘要值,然后就是对象类型,大小
- #查看git版本
- C:\Users>git --version
- git version 2.20.1.windows.1
-
- #创建测试目录
- D:\>mkdir gittest
-
- D:\>cd gittest
-
- #git 初始化
- D:\gittest>git init
- Initialized empty Git repository in D:/gittest/.git/
-
- #创建文件index.txt
- D:\gittest>echo "version 1" > index.txt
-
- # index.txt加入暂存区
- D:\gittest>git add index.txt
-
- # 查看所有对象内容
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
-
- # 查询sha-1对应的文件内容,该对象对应的内容就是index.txt内容
- D:\gittest>git cat-file -p 6c58b76a52188643965f3a6704166e8e0424b7fe
- "version 1"
-
- # 创建文件index2.txt
- D:\gittest>echo "version 2" > index2.txt
- # index2.txt加入暂存区
- D:\gittest>git add index2.txt
- # 查看所有对象内容
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
- 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
-
- # 查询sha-1对应的文件内容,该对象对应的内容就是index2.txt内容
- D:\gittest>git cat-file -p 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71
- "version 2"
-
- #创建新文件夹
- D:\gittest>mkdir dir
-
- #创建新文件夹中的新文件
- D:\gittest>echo "version 1, inside" > ./dir/inside.txt
-
- # inside.txt加入暂存区
- D:\gittest>git add ./dir/inside.txt
-
- # 查看所有对象内容
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
- 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
- bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21
-
- # 查询sha-1对应的文件内容,该对象对应的内容就是inside.txt内容
- D:\gittest>git cat-file -p bf97e71de76bcff2bd8aba44710aa5e665eacb99
- "version 1, inside"
-
- #提交到本地仓库
- D:\gittest>git commit
-
-
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
- 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
- bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21
- d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105
-
-
-
- D:\gittest>git commit
- [master (root-commit) 629a4cf] commit 1
- 3 files changed, 3 insertions(+)
- create mode 100644 dir/inside.txt
- create mode 100644 index.txt
- create mode 100644 index2.txt
-
- # 查看所有对象内容,commit之后多了两个tree和一个commit
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38
- 629a4cf0fdb33390ad5774b10244512e3d400407 commit 169
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13
- 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13
- bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21
- d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105
-
- #查看一个commit
- D:\gittest>git cat-file -p 629a4cf0fdb33390ad5774b10244512e3d400407
- tree d5c2b878425995af5ddc5202f7058a1ff372b3f3
- author iaiti<xx@qq.com> 1617247696 +0800
- committer iaiti<xx@qq.com> 1617247696 +0800
-
- # 查看其中一个tree
- D:\gittest>git cat-file -p d5c2b878425995af5ddc5202f7058a1ff372b3f3
- 040000 tree 39bdea2300491cc90f47551887bfe9503cd4a9d9 dir
- 100644 blob 6c58b76a52188643965f3a6704166e8e0424b7fe index.txt
- 100644 blob 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 index2.txt
-
-
- # 更改文件内容
- D:\gittest>echo "version 2" > index.txt
-
- D:\gittest>git add index.txt
-
- D:\gittest>echo "version 1 new" > index.txt
-
- D:\gittest>git add index.txt
-
- D:\gittest> git cat-file --batch-check --batch-all-objects
- 0b596a83945ca790976a10bbf005262f1cefe4cc blob 17 (version 1 new)
- 39bdea2300491cc90f47551887bfe9503cd4a9d9 tree 38 (inside.txt)
- 629a4cf0fdb33390ad5774b10244512e3d400407 commit 169 (commit)
- 6c58b76a52188643965f3a6704166e8e0424b7fe blob 13 (version 1)
- 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 blob 13 (version 2)
- bf97e71de76bcff2bd8aba44710aa5e665eacb99 blob 21 (version 1, inside)
- d5c2b878425995af5ddc5202f7058a1ff372b3f3 tree 105 (dir index.txt index2.txt)
-
- D:\gittest>git cat-file -p 0b596a83945ca790976a10bbf005262f1cefe4cc
- "version 1 new"
-
-
- #提交第二次
- D:\gittest>git cat-file -p beaeb2b94a88d6cf03c096f667859239065d1ba8
- tree 4fca214cabbc6f8c6a7243f9ea780b66ee895993
- parent 629a4cf0fdb33390ad5774b10244512e3d400407
- author iaiti <xx@git.com> 1617247963 +0800
- committer iaiti <git@xx.com> 1617247963 +0800
-
- Commit 2
多次更改和提交两次后,所有对象的对应关系
branch 其实就是一个指向某个commit的指针文件,一般被存放在./.git/refs/heads里面,所以branch只是跨commit而已,按照上图所指示出来的,指向的其实就是master分支
head指向最新commit
tag相当于是静态的 branch ,被存储在./.git/refs/tags里面的文件中。它并不跟随HEAD移动。通常用于标记一个特定的commit,例如某个版本的代码,以方便checkout。
reset是记录重设,有三种模式
git reset 17cf9ea15f6c63ec04f232c5cd72e0c1b3f657fd
--hard commit记录重设,但是如果远程仓库已经commit,可以使用git push --force
--mixed commit记录重设,工作区文件修改,暂存区的记录会重置,相当于没到git add阶段,相当于撤销add
--soft commit记录重设,工作区文件修改和暂存区的记录都会保存
三种模式总结来说就是,相当于做了版本回退,并控制文件是否回退到暂存区前
而reverse,也是回退,但是不是重置commit,而是多出一条commit ,提醒其他的开发者或者公司同事,这里有恢复操作。可以
和reset对比结合看。
问题来了,reverse还有commit,reset的话中间的commit就不见了, 我要回滚怎么操作?
git reflog记录操作,回滚回之前重置的commit记录。
- D:\gittest>git ls-files --stage
- 100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0 dir/inside.txt
- 100644 0b596a83945ca790976a10bbf005262f1cefe4cc 0 index.txt
- 100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0 index2.txt
- D:\gittest>
- D:\gittest>echo "version test index" > index.txt
- D:\gittest>
- D:\gittest>git ls-files --stage
- 100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0 dir/inside.txt
- 100644 0b596a83945ca790976a10bbf005262f1cefe4cc 0 index.txt
- 100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0 index2.txt
-
- D:\gittest>git add index.txt
-
- D:\gittest>git ls-files --stage
- 100644 bf97e71de76bcff2bd8aba44710aa5e665eacb99 0 dir/inside.txt
- 100644 be06e3be42f6a2955d61750c86646b7869177f47 0 index.txt
- 100644 8231f0fdc862f06b2bd7b7bfd2f42082d3086b71 0 index2.txt
- D:\gittest>
-
-
- D:\gittest>echo "version test index" > index.txt
-
- D:\gittest>git add index.txt
-
- git commit -m comit3
-
- D:\gittest>git log
- commit b3a0d90be0da1862b4c82fb6beafffaf4113148e (HEAD -> master)
- Author: <E8><94><A1><E5><9D><A4><E6><89><BF> <xx.com>
- Date: Thu Apr 29 19:51:51 2021 +0800
-
- Revert "comit3"
-
- This reverts commit 6fccca25df481aa1d53ad60075bb37d5e87d8593.
-
- commit 6fccca25df481aa1d53ad60075bb37d5e87d8593
- Author: <E8><94><A1><E5><9D><A4><E6><89><BF> <xx.com>
- Date: Thu Apr 29 19:51:21 2021 +0800
-
- comit3
变基,Git - git-rebase Documentation 可以查看相关指令信息,
git rebase -i [startpoint] [endpoint] 给用户交互界面进行操作
挑选变基的commit
git rebase -i 674c40b
然后移除多余的commit信息,s的话是合并前面的提交
从这里可以看到,变基可以合并我前面提交无用的记录。让整个提交的历史更加的简洁,之前有网友举例,vue作者尤雨溪就有这样的处理。
rebase分支不要使用在公共分支上。
除了合并提交信息,让其更简洁外,是不是还有其他作用,都是合并,那和merge区别是什么,需要这样思考。
假如我有一条功能分支比较久没同步线上代码,或者主分支其实多人合作合并频繁的时候,按照平时的操作都是拉一条分支,然后将master merge到自己分支
结果是这样的
而变基能让自己的一条分支形成直线,不受其他的干扰。
总结来说,merge是当前开发分支领先于要合并的分支,那就merge过去,比如开发功能和测试完毕想合并到线上,就是用merge。
如果当前分支许久没拉下来,落后master的,就用rebase,就只把当前的内容合并到自己分支上,而不用理会是什么分支合并过来的。master主分支才需要查看谁合了什么上去。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。