Git_Rebase
Git_Rebase
- 概念
- 与 `git merge` 的区别
- git rebase -i 交互式变基
- 使用场景
- 修改提交信息
- 删除某个文件的提交
- 拆分提交
- 合并提交
- 删除提交
- 调整提交顺序
- 自动变基
- autosquash
- 注意
概念
它可以将与另外一个分支的最近的共同提交记录的后的两部分进行变基(重写),并以另外一个分支的提交记录在前,当前分支的提交记录在后的方式,插入到最近共同提交记录的后面,从而创建一个更线性的提交记录。
与merge不同,merge是将两个分支的提交记录合并到在一起。rebase则会将这些提交记录都重写(会生成新的hash值)

与 git merge 的区别
| 方面 | git merge | git rebase |
|---|---|---|
| 历史记录 | 保留分支合并的痕迹 | 形成线性历史 |
| 提交哈希 | 保留原提交哈希 | 创建新的提交哈希 |
| 解决冲突 | 一次解决 | 如果多个提交都进行了修改,可能需要多次解决 |
| 使用场景 | 公共分支合并 | 本地分支整理 整合最新代码 |
# 在开发功能时,获取主分支的最新更新
# 这里用merge的化,会创建一个合并记录
git rebase origin/main# 整理最近3个提交
git rebase -i HEAD~3
git rebase -i 交互式变基
通过命令行输入 git rebase -i <commit_hash>`` # 从某个提交开始(不包括该提交)
命令会展示该commit_hash 后的所有提交记录,并可以通过vim的方式去编辑他们。

| 命令 | 缩写 | 功能 | 使用场景 |
|---|---|---|---|
pick | p | 保留该提交(不变) | |
reword | r | 保留提交但修改信息 | 修改 提交信息 commit message |
edit | e | 保留提交但暂停修改 | 拆分提交,删除某个文件的提交 |
squash | s | 将提交合并到前一个提交 | 合并提交 |
fixup | f | 类似 squash,但丢弃提交信息 | |
drop | d | 删除该提交 | |
| 调整行的先后顺序 | 调整提交记录顺序 |
使用场景

请不要在意这些奇奇怪怪的提交🤣
修改提交信息
# reword 修改提交信息
# 我想把 c892c8ea 这里的信息
git rebase -i a4fa4602

将c892c8ea这里的 pick修改为reword

通过 :wq 保存后

会提示让我们修改,我们修改后 再次通过:wq保存后

这里可以看到,我们这里面的commit_hash 变了,我们指定修改的commit_msg也变了。
删除某个文件的提交
git log --follow <文件路径> 查看完整的修改记录包括移动及重命名

- 查到最下面的一个
commit_hash也就是最初创建该文件的hash值 git rebase -i <最初修改的commit_hash>~<最初修改的commit_hash>~代表创建该文件前的一个提交记录<最初修改的commit_hash>~等价与<最初修改的commit_hash>~1


- 把所有有修改记录的
commit_hash都修改为edit并通过:wq保存。表示暂停这几个提交并进行修改。

- 这里标识git的指针暂停到了这个
commit_hash上,当前工作区的状态也就回到了当前commit_hash的文件内容 - 删除想要删除的文件
git rm <文件路径>,也可以直接通过idea的文件窗口删除


- 修改完成后,执行
git rebase --continue标识当前标记为edit的修改已经修改完成,并继续执行rebase - 执行上面这个命令后会进入到这个页面让我们修改提交信息,如果不想修改的化直接
:wq即可

- 执行后发现,因为
3c943e9f也对这个文件进行修改,所以这里产生了一个冲突,我们这里需要解决他

git status查看当前git 状态


- 继续删除这个文件即可,后面的两个也按照这样执行即可。当最后一个记录的文件删除完成后,执行
git rebase --continue

- 最后这样就变基完成了

- 对比下原来的提交记录,
DesUtils.java的文件彻底没了- 新的

- 旧的
- 新的

拆分提交
我觉得这个提交记录一次性提交了太多东西,我想将这个提交拆成两份,分开提交。

- 依然是找到这个
commit_hash的上一个 - 执行
git rebase -i ab5e6afb06550a083510d2ec2607bb77c892018b~ - 修改者一个为
edit并:wq保存

git reset HEAD~将头执行上一个commit_hash,也就是当前还未提交的状态

- 用
git add添加想要第一次提交的文件,并使用git commit -m <拆分后的第一次提交信息>

- 其中如果有添加错了的想要撤回的可以通过
git restore --staged <file>将文件撤销粗暂存区


- 第二次拆分

- 第三次拆分

- 最后通过
git rebase --continue结束这一次的变基 可以看到这里已经拆分好了,并且生成了新的commit_hash,但是要注意这里的时间并不是原来的而是新的。

合并提交
当觉得有多个合并的时候,可以通过合并提交后,再将本地分支上传到远程

我想把ImageUtil从5da0d2e1中拆分出来并且,将后面几个相关的提交合并成一个。
git rebase -i 5da0d2e13032a32c48e6498b67f7505a22c34cb3~- 因为 我要拆分
5da0d2e1所以使用edit:wq保存后 为什么都用~~fixup~~呢 ,是因为我想以~~5da0d2e1~~拆分后的~~ImageUtil~~相关的为~~最终提交信息~~的这里遇到了一个**bug **如第二个用**fixup**的话会使用**5da0d2e**的提交信息,而不是**5da0d2e1**拆分后的**ImageUtil**相关的为最终的提交信息,所以这里使用**squash**来修改合并并提交信息


git rm -r --cached <file...> 从暂存区删除文件,但是保留文件- 这里因为
ImageConstants.java后面都没有修改了,如果直接通过git rm删除的话,后面也不会有这个文件的冲突,单ImageUtils.java不会这样,因为后面对他进行了修改,所以会产生冲突所以使用git rm也没有关系

- 通过
git rebase --continue结束这一次的提交并修改了提交信息,这里可以看到Image这两个文件不在本次提交中

再然后将 这两个文件单独提交上去并配上最终的提交信息- 然后将这个两个文件单独提交上去,

再执行因为后面没有冲突及暂停修改的操作了,所以这里直接就执行~~git rebase --continue~~~~fixup~~合并了,当然你也可以使用~~squash~~~~再合并提交信息 ~~- 这里的存储层就是bug 本身一个是我们
新增图像工具类这个信息的,但是这里直接使用的上一个提交信息

- 再执行
git rebase --continue,因为后面没有冲突及暂停修改的操作了,只有一个合并提交信息的操作,我们修改成最终我们想要的提交信息即可 再通过:wq保存

- 这就表示
rebase操作执行完成了

- 达到了 想要的效果 拆分了,且合并了提交。

删除提交
删除这个提交,这个提交的内容也会丢失,如果后面的提交对其中有修改的话,也会产生冲突。慎用。

git rebase -i 7340623dd0fa80d0065c7a26342730f55f03c554~- 将想要删除的那一条修改为drop

:wq保存后没有冲突的话,就会直接成功

- 提交已经被删除

调整提交顺序
我想要这两个红框交换下顺序

git rebase -i e6761477ac8da8204a323791ba36124a2c7f0626~- 进入交互式命令后将两个提交记录交换顺序即可


:wq保存后可看见效果,这个时间是会变的

自动变基
autosquash
自动变基,仅限于自动合并多个提交到一个提交,他会将带有 fixup 开头信息的提交 都自动合并到指定的提交中。
- 这5次提交分别以下命令提交的。
git commit --fixup fa9a185671449b9a0504046c142cc18930011550git commit --fixup fa9a185671449b9a0504046c142cc18930011550git commit -m "fixup! 修改包 com.mfyuan"git commit -m "正常提交"git commit --fixup fa9a185671449b9a0504046c142cc18930011550
- 可以看到idea 已经识别到了
fixup要合并的记录,但是第三条居然也被识别到了。

- 执行
git rebase -i --autosquash HEAD~6自动化变基最近6条提交记录 需要包含指定合入的那一条记录。 - 这个会自动帮忙我们编辑好,并把我们正常提交的挪到了后面,直接
:wq保存即可

- 这里可以看见他把提交内容都合并到了一个里面,只有正常提交内容不在里面

注意
- 不要对已经推送到公共仓库的分支进行 rebase
- 只对本地、未推送的分支使用 rebase
