基础概念
Git 是一个代码版本管控的工具,是一个内容寻址文件系统,即简单的键值对数据库。
Git 的一些基础基础知识
- 版本库:git在本地开辟的一个存储空间,一般在 .git 文件里。
- 工作区(workspace): 就是编辑器里面的代码,平常开发直接操作的就是工作区。
- 索引区/暂存区(index/stage):暂时存放文件的地方,
git add后也就将工作区代码放到了暂存区(缓冲区)。 - 本地仓库(Repository):
git commit后就是将暂存区的代码放到本地仓库。 - 远程仓库(Remote):线上代码存放的地方,如 github/gitee。
他们之间的关系是这样子的:

本文伊始,需要知晓一些git 相关 基础命令,
如果对基础linux的命令不熟悉请查看 这里
git cat-file -t <sha1-hash> # 查看文件类型 commit 取前四位即可
git cat-file -p <sha1-hash> # 查看文件内容
cat .git/refs/heads/master # 查看master指向的文件
git ls-files # 查看索引区文件, 也就是index的内容
git ls-files -s #查看 索引/暂存 区的文件内容初始化
本文环境 前面是win10 => cmder,后面是mac => iterm2+zsh
先在 porn....呸,github 先创建一个清爽的远程仓库
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cU6Bh2tL-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2022-08-10-23-09-41-image.png?msec=1684158868612)]41-image.png" title="" alt="" width="50"> #yyds干货盘点#GIT浅析原理_git_02](https://file.cfanz.cn/uploads/png/2023/12/02/8/c9Mf688SfD.png)
推荐三种方式 往空仓库“填充”代码。
咱们先别顺着 Git 这小子,先把它克隆下来, 看看 .git 文件
D:\assets
λ git clone https://github.com/OFreshman/gitTest.git
Cloning into 'gitTest'...
warning: You appear to have cloned an empty repository.
λ rm -rf .git/*.sample # 为了看起来干净,删除了sample文件
D:\assets\gitTest (main -> origin)
λ tree .git /f # 以树形结构递归查看所有文件夹即文件夹,
D:\ASSETS\GITTEST\.GIT
│ config # 仓库本地配置文件
│ description # 描述 用于GitWeb
│ HEAD # 工作区目录指向的分支
├─hooks # 存放一些shell脚本,可以设置特定的git命令后触发相应的脚本
├─info # 附加信息
│ exclude # git文件排除规则。类似 .gitnore
├─objects # 所有文件存储对象
│ ├─info # 对象存储的附加信息,存储着打包后的文件名
│ └─pack # git 压缩对象
└─refs # 夹存储着分支和标签的引用
├─heads # 分支对应对象
└─tags # 标签各文件详情补充
.git/info
info/exclude,初始化时只有这个文件,用于排除提交规则,与 .gitignore 功能类似。区别在于.gitignore 这个文件本身会提交到版本库中去,用来保存的是公共需要排除的文件;而info/exclude 设置的则是你自己本地需要排除的文件,他不会影响到其他人,也不会提交到版本库中去。
info/refs,如果新建了分支后,会有info/refs文件, 用于跟踪各分支的信息。对于刚克隆下来的仓库 可以通过命令去生成 info/refs 文件

FETCH_HEAD
指向上一次的 fetch 的commit
➜ gitTest git:(main) cat .git/FETCH_HEAD
> d4166b7319f1c85b7a86718f6a0387e0e9b1fa2c branch 'main' of github.com:OFreshman/gitTest如果需要合并可以这样
git merge FETCH_HEAD因为刚刚 fetch 的是main分支, 上面命令相当于执行 git merge remote/main
.git/index
二进制暂存区(stage)
COMMIT-EDITMSG
COMMIT-EDITMSG 是一个临时文件,存储最后一次提交的message。有提交才会有这个文件夹。
logs
存储提交、操作日志,git reflog 依赖此文件夹。

refs
refs/heads/ 文件夹内的 ref 一般通过 git branch 生成。git show-ref --heads 可以查看;
refs/tags/ 文件夹内的 ref 一般通过 git tag 生成。git show-ref --tags 可以查看。
refs/remotes/ 文件一般是存放远程的分支。git fetch 就会更新里面的内容
上面大概说明了.git 各子文件的作用。因为这是个空仓库(warning: You appear to have cloned an empty repository),所以没有分支,即使看起来像有(main -> origin), 此时已经初始化了一个git仓库了(相当于执行了 git init),再次执行 git init 会提示 重复初始化已经存在的仓库了。
λ git init
> Reinitialized existing Git repository in D:/assets/gitTest/.git/注意:线上的默认分支是main,本地是master。
另外此时本地 git branch 无法查看分支,需要 git add && git commit 后才能查看。如果是 git init 初始化 会有 分支,且 存在 .git/branchs 文件夹。
refs/heads, refs/tags 目前都为空(因为克隆的就是空仓库), HEAD 指向工作区的分支
λ cat .git/HEAD
ref: refs/heads/maingit status 查看到未提交的代码时为啥不一样,其实就是对比了暂存区和工作区的文件内容。index(索引区) 始终保存着最新的待提交的文件
工作区到暂存区(add)
新建一个文件,并写入内容 hello txt
echo 'hello txt'>hello.txt此时 该文件在工作区(workspace),未被追踪(untracked),将其添加至 索引区(index)
git add hello.txt
可以看到增加了两个文件 index, objects/32,objects 里面是一个个hash对象,hash值前两位为一级文件夹名,剩余值为相应二级文件夹名,前两位相同的会被归到同一个文件夹,而index是存放暂存区文件的文件夹。
这里就产生了一个疑问:为什么Git要这么设计目录结构,而不直接用Git对象的40位hash作为文件名?原因是有两点:
- 有些文件系统对目录下的文件数量有限制。例如,FAT32限制单目录下的最大文件数量是65535个,如果使用U盘拷贝Git文件就可能出现问题。
- 有些文件系统访问文件是一个线性查找的过程,目录下的文件越多,访问越慢。
objects 一级子目录数量就变成了 <= (10+26)^2。大大减少了数量,相应的也提升了检索速度
objects 里面的hash对象类型有三种: blob、commit、tree
git 提供了相应的命令去查看类型, 查看的时候只需要带上文件夹名(32)+ hash子文件前四位(4b9a)。四位也可以只要是唯一。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQktlLkM-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-09-23-21-03-image.png?msec=1684158868494)] #yyds干货盘点#GIT浅析原理_Test_06](https://file.cfanz.cn/uploads/png/2023/12/02/8/fD2I85740E.png)
可以查看该文件内容
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OM8IvIw4-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-09-23-25-24-image.png?msec=1684158868493)] #yyds干货盘点#GIT浅析原理_git_07](https://file.cfanz.cn/uploads/png/2023/12/02/8/EbC3351b1P.png)
也可以查看文件长度
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0X47B72-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-00-13-46-image.png?msec=1684158868495)] #yyds干货盘点#GIT浅析原理_Test_08](https://file.cfanz.cn/uploads/png/2023/12/02/8/6c95MA90Nc.png)
当重复添加相同内容的不同文件时,objects 不会改变,因为 32-4b9a6927b8f2217f751be4f8379e0d093856ab 存的是文件内容且Git有重复检测。
但 32-4b9a6927b8f2217f751be4f8379e0d093856ab 不止是文件内容的hash,而是包含 类型 + 长度 + \0(linux字符串结束符) + 文件内容 的 sha1 hash 值,可验证一下。(shasum 是mac 安装的命令包,默认输出sha1 hash)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hyUJlU3G-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-00-04-16-image.png?msec=1684158868517)] #yyds干货盘点#GIT浅析原理_git_09](https://file.cfanz.cn/uploads/png/2023/12/02/8/Fac17U0K6e.png)
还有个命令可以佐证 得到的hash
how-is-the-git-hash-calculated
(printf "commit %s\0" $(git cat-file commit 324b9a | wc -c); git cat-file commit 324b9a)|shasum
> 324b9a6927b8f2217f751be4f8379e0d093856abshasum 是获取文件的各种hash值 的函数,默认SHA1。参考mac下如何获取文件MD5校验值和SHA1校验值 - 掘金
此时索引区文件(-s 是 --stage 的缩写)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O52fyC4A-1685028681289)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-20-49-38-image.png?msec=1684158868513)] #yyds干货盘点#GIT浅析原理_暂存区_10](https://file.cfanz.cn/uploads/png/2023/12/02/8/7B1c5YeJ08.png)
加 -s 得到的事索引区 文件的 权限 + blob对象 + 0 + 文件名
为了对比看效果,此时 增加新文件hello.txt并去修改文件 hello.txt , git status查看状态的时候 之前是 未跟踪(untracked), 现在是修改(modify)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-40I0ffRc-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-07-48-image.png?msec=1684158868639)] #yyds干货盘点#GIT浅析原理_Test_11](https://file.cfanz.cn/uploads/png/2023/12/02/8/b5W51YFTbV.png)
将新文件提交,那么 .git/objects 中的 blob 对象就会改变
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j0JCRMHb-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-11-33-image.png?msec=1684158868529)] #yyds干货盘点#GIT浅析原理_Test_12](https://file.cfanz.cn/uploads/png/2023/12/02/8/VVY61853cV.png)
索引区到本地仓库(commit)
接下来对上面的文件进行commit
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x20P3EEC-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-23-41-image.png?msec=1684158868530)] #yyds干货盘点#GIT浅析原理_暂存区_13](https://file.cfanz.cn/uploads/png/2023/12/02/8/C99c97JVd1.png)
附带的信息:这是根提交(root-commit ,第一次),提交对象的hash值,文件改变数量和行数,文件权限(之前提到过),文件名。
commit 之后 可使用 git rev-parse HEAD:<file> 查看当前版本对象的 sha1值
git rev-parse HEAD:hello.txt5b10c6a97b7b4132c2ad4d6d80ceddd2b8a4fdba
此次提交的对象类型为 commit
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YGy1N4xG-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-32-03-image.png?msec=1684158868580)] #yyds干货盘点#GIT浅析原理_Test_14](https://file.cfanz.cn/uploads/png/2023/12/02/8/S17091Y2Oa.png)
这个 commit 对象的内容含有 tree 类型对象,以及仓库作者和提交者信息,提交信息。
.git 文件 也有一些变化
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GveYfJNT-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-38-50-image.png?msec=1684158868655)] #yyds干货盘点#GIT浅析原理_Test_15](https://file.cfanz.cn/uploads/png/2023/12/02/8/3b0ZELA87N.png)
logs 是 git 历史相关的文件。objects 里增加了前面提的的两个对象(commit,tree)以及heads 里面增加了main。也就在此时本地也有了分支 main (git branch 查看)。
HEAD 是一个指向当前工作分支的指针,目前指向main, refs/heads/main 是啥?就是 main 分支指向的 最新提交对象。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZYiKGGuY-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-59-31-image.png?msec=1684158868512)] #yyds干货盘点#GIT浅析原理_暂存区_16](https://file.cfanz.cn/uploads/png/2023/12/02/8/464RB7OB0d.png)
tree 对象含有两个blob 文件,仔细观察可以发现就是之前 add 时 添加的两个blob对象
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CEfEvQZp-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-21-46-34-image.png?msec=1684158868529)] #yyds干货盘点#GIT浅析原理_git_17](https://file.cfanz.cn/uploads/png/2023/12/02/8/V1BQcbb36V.png)
现在 objects 的里对象的关系如下
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzrKIdz1-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-23-42-54-image.png?msec=1684158868514)] #yyds干货盘点#GIT浅析原理_Test_18](https://file.cfanz.cn/uploads/png/2023/12/02/8/O0431G5Nb4.png)
为了探究其中的奥秘,再次更改 hello.txt(vim hello.txt, git add, git commit),具体细节就不展示了,给一个objects对比图
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmM4VbCJ-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-23-17-26-image.png?msec=1684158868655)] #yyds干货盘点#GIT浅析原理_git_19](https://file.cfanz.cn/uploads/png/2023/12/02/8/WWPQ51FU42.png)
新增了 四个对象, git cat-file -p 一一查看新增的四个内容
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6geeXsx-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-10-23-24-32-image.png?msec=1684158868627)] #yyds干货盘点#GIT浅析原理_暂存区_20](https://file.cfanz.cn/uploads/png/2023/12/02/8/6baO97437D.png)
对于这次commit 对象 多了一个 父级对象(parent)。 简单梳理一下就是
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FQLAvLEE-1685028681290)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-12-45-57-image.png?msec=1684158868563)] #yyds干货盘点#GIT浅析原理_Test_21](https://file.cfanz.cn/uploads/png/2023/12/02/8/1ac2MBcRPA.png)
或许能从前面两张图总结出一些规律
- 每次 add 都会生成一个blob 对象
- 每次 commit 都会生成 commit 和 tree 对象以及若干个blob对象 (blob数量 = 新增/修改的文件数)
- tree 对象 始终包含最新的所有文件
接着验证一下,更改 test.txt、hello.txt, 增加文件 demo.txt。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njdaANQO-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-00-16-05-image.png?msec=1684158868596)] #yyds干货盘点#GIT浅析原理_git_22](https://file.cfanz.cn/uploads/png/2023/12/02/8/111A6b1LaP.png)
git add . 时会增加三个 对象
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F61JFFRb-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-00-10-30-image.png?msec=1684158868687)] #yyds干货盘点#GIT浅析原理_Test_23](https://file.cfanz.cn/uploads/png/2023/12/02/8/5109219e17.png)
git commit 之后增加了两个对象, 一个是commit类型(), 一个是commit类型包含的tree类型
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GLWlH6r9-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-08-36-44-image.png?msec=1684158868661)] #yyds干货盘点#GIT浅析原理_暂存区_24](https://file.cfanz.cn/uploads/png/2023/12/02/8/0559J46Ud2.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7rkRWOaC-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-08-43-34-image.png?msec=1684158868607)] #yyds干货盘点#GIT浅析原理_Test_25](https://file.cfanz.cn/uploads/png/2023/12/02/8/Na5EV74f70.png)
总共增加了五个对象,它们的关系如下图
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TORAD9KZ-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-21-02-03-image.png?msec=1684158868591)] #yyds干货盘点#GIT浅析原理_Test_26](https://file.cfanz.cn/uploads/png/2023/12/02/8/d75873FRe3.png)
至此,前面的推断被证实,且在用户添加/提交文件的时候,objects 的内部变化也能很好的体现。objects 里保存在暂存区和本地仓库的文件对象。
main 分支指向最新的提交,暂存区包含最新的所有文件。
➜ gitTest git:(main) cat .git/refs/heads/main
0d8d0eb0446d7bf92a32512089fa927314675ac9
➜ gitTest git:(main) git ls-files -s
100644 598bc0d8552fb08de29c7fcd317cacf09c0f237b 0 demo.txt
100644 acdf79a141b2f07dca7b715d606b23307d669f94 0 hello.txt
100644 ba0ba9399c8a2336b1aab6a61fa499b012561588 0 test.txt此时提交历史就是上图中 三个 commit 的提交
git log --oneline
* 0d8d0eb (HEAD -> main) 2nd commit
* de07e86 change hello.txt
* 779c005 added two files仓库含有文件
这是常见的情况,但是前面为了简化变化,仅仅使用了文件。
使用文件夹有一些不一样,前面说过 每次提交都会产生一个 commit、tree、若干个blob(取决于文件数量) 对象,当有文件夹时,commit 和 tree(root) 依旧会存在, 仓库的一级 文件/文件夹 会分别作 blob/tree(1-level) 被包含在 tree(root) 下面,如果一级文件夹里面包含文件夹,那么其子文件依旧会作为 tree(2-level), 包含在 其 父级 tree(1-level) 下, 该子文件夹的子文件 会被作为blob包含在子 tree(1-level) 下
比如仓库有 一个文件夹 F,F里有个文件 f.txt,两个文件 a.txt, b.txt。
add 会产生 三个 blob(f.txt, a.txt, b.txt)
commit 会产生 两个tree(本身一个, F文件夹一个), 一个commit

commit > tree > [tree(F) > blob(f.txt) , blob(a.txt), blob(b.txt)]
不一样的就是 文件F 也作为一个tree, 这个 tree 含有一个 blob, 即该文件夹下的子文件。
前面文字说的可能有点绕,现在再举个🌰,我在仓库建立一些文件

第一次 add 后,有五个 blob 对象,就是那五个文件

commit 后 会有 1个 commit、6个tree(1+5),总共 12 个对象

和Objects对象图
分支
分支大家都不陌生, 在Git 里,分支就是一个特殊(具有名字)的指针,指向某个 commit。
另外 git 里面还有个 HEAD 文件
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hD9ekjuZ-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-21-23-17-image.png?msec=1684158868476)] #yyds干货盘点#GIT浅析原理_Test_31](https://file.cfanz.cn/uploads/png/2023/12/02/8/a4bfKL56I9.png)
这也是个指针,在活跃的分支上指向最新的提交。简单理解就是 切到哪个分支,它就指向哪个分支。可以相关命令查看一下
➜ gitTest git:(main) cat .git/HEAD
ref: refs/heads/main
➜ gitTest git:(main) cat .git/refs/heads/main
0d8d0eb0446d7bf92a32512089fa927314675ac9有这样的关系: HEAD => main => lastest commit
接着新建一个 dev 分支,此时 .git/refs, .git/logs 都改变了
tree -I <ignore-file> <file> 树形展开file文件并忽略 ignore-file
前面说过 logs 表示git 的提交历史,此时查看提交历史
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r9YS86lW-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-21-51-21-image.png?msec=1684158868475)] #yyds干货盘点#GIT浅析原理_git_32](https://file.cfanz.cn/uploads/png/2023/12/02/8/81JaTIcQ45.png)
括号里面表示分支 main 和 dev 都指向 0d8d0ed 的 commit 对象,且 HEAD 指向 main(当前在main分支上);
简单画了个图
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nMxaaEbY-1685028681291)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-11-22-07-02-image.png?msec=1684158868497)] #yyds干货盘点#GIT浅析原理_git_33](https://file.cfanz.cn/uploads/png/2023/12/02/8/19BW98Tf7P.png)
在 master 上产生一个 commit,dev 也产生一个(停在此分支),就有如下关系
然后 再去合并main 会发生什么?
- 产生一个新的 commit;
- dev 指向新的 commit;
那么删除分支会删除分支指向的 commit 吗?答案是不会的
至此,分支的 创建、切换、合并、删除都演示完了。
记住一句话: 分支是一个有名字的指针,指向 某个 commit。
变基 Rebase
有了上面的知识,变基就很好理解了。主要有两种情况
git rebase <branch>变基分支git rebase -i <commit-id>变基提交
先说情况2,理解了情况2,情况1就很好理解了。
变基到某个提交
变基,变基,就是改变基底,通俗一些就是基于哪个commit。变基到某个提交也有两种情况, 本分支或者其它的分支上的提交。其实原理差不多,这里演示变基其他分支的提交。
为了方便查看效果,删除原有仓库及文件,重新初始化,并且进行一个提交。
# 清空仓库
➜ gitTest git:(new) rm -rf .git
➜ gitTest rm hello.txt test.txt
# 初始化
➜ gitTest git init
已初始化空的 Git 仓库于 /Users/Public/Learn/git/gitTest/.git/
➜ gitTest git:(master) echo "master txt" > master.txt
➜ gitTest git:(master) ✗ git add . && git commit -m "1st commit"
[master(根提交) b505c69] add master.txt
1 file changed, 1 insertions(+), 0 deletions(-)
create mode 100644 one.txt接着切出 dev 分支,产生三个提交, master 上产生两个
可以看到 b505c6 是他们的共同提交,也可成为基底。
然后 dev 上变基 到 master上第一个提交 80b77b
git rabse -i 80b77b我选择 sword 更改三条提交注释, 后面都加上了 rebase
变基成功。
新产生了三个 commit 对应着 dev 上原来的三个 commit, 并且原来的三个commit 消失了,dev的提交历史如下
master 分支不受影响,关系如下图。
变基分支
假设现在 main 分支有1个提交 9b789c,新建分支 dev, 此时 main 、dev 分支的基底就为9b789c2。
接着 在 dev 上产生了一个提交, main 上产生了2个提交,
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uouHjBo-1685028681292)(file:///Users/ethanyin/Library/Application%20Support/marktext/images/2023-05-13-17-03-15-image.png?msec=1684158868498)] #yyds干货盘点#GIT浅析原理_Test_34](https://file.cfanz.cn/uploads/png/2023/12/02/8/e86J4R1QMO.png)
用图总结一下
此时 在 dev 分支上执行 git rebase main(不加 -i 就是啥都不改变,就是直接产生若干新提交到 main指向的提交后)。
dev 提交历史
main分支不受影响
关系如图。
总结
变基就是 将当前分支 的所有commits都变为新的 commits,这些新commits的第一个的上一个提交为变基的目标 commit。前面说过,分支其实是个有名字的指针(类似HEAD),指向当前分支的最新 commit,分支变基不过是变基目标commit 不一样而已!








