☝️🤓重学 Git(二)—— 处理综合问题

背景

在学习过 Git 的常用、进阶操作之后,我们再来结合工作中的实际场景以进一步提高实战能力。 如果对 Git 的基础还不够扎实,可以看看前一篇文章。 上集回顾:☝️🤓重学 Git(一)------ 掌握从常用到进阶的指令操作

首先说一下通过这篇文章大家能收获什么:

  1. 继上一章,对于一些 Git 指令的补充。
  2. 使用一系列 Git 指令熟练处理工作中的问题。

Git 指令补充

在模拟实际场景前,我们先对一些指令的作用、比对,以及一些操作进行深入探讨。

强推的细节

强制推送是指将本地分支的提交强制推送到远程仓库,覆盖远程仓库中的相应分支。切记!强制推送也可能导致数据丢失或冲突,因此需要谨慎使用。

这边仅介绍工作中常见的两种强推方式: --force--force-with-lease

--force

shell 复制代码
git push -f/--force origin <branch-name>

这种强推是没有任何协商的,建议仅在单人开发分支使用,使用这个选项时,Git 不会检查是否有其他人同时在远程仓库上进行了提交,可能会导致数据丢失或冲突。

--force-with-lease

shell 复制代码
git push --force-with-lease origin <branch-name>

相对更安全的强制推送选项,在执行之前会先检查远程仓库上的提交历史,与本地提交历史比较。只有在本地仓库的提交历史是基于远程仓库的最新提交时,才会执行推送操作。个人建议仅使用这种强推。

blob通配符筛选文件,进行批量操作

通配符在需要批处理文件记录时有很大的用处。

案例:ts 项目,工作区有修改过的 ts 文件,此时执行了 npx tsc --build,产生了大量的 .d.ts、.js、.js.map 等文件(但并不需要这些文件),此时手动筛选出修改过的文件就比较考验眼力了,因此可以通过通配符,将这些格式的文件清除。

相关的操作方式还请阅读相关文档:Git 使用通配符扩展的Git命令

revert和reset对比

两者的核心功能都是撤销 Git 提交,相关的区别如下:

  1. 作用对象

    • revert:用于撤销一个或多个已提交的提交记录。它会创建对应数量的新提交来撤销指定的提交内容。
    • reset:用于修改当前分支的位置,并丢弃一些提交记录。
  2. 修改历史记录

    • revert:会保留之前的提交记录。
    • reset:可以通过不同的模式来修改历史记录。使用 --soft 模式会移动当前分支的指向,但不会更改工作目录和暂存区。使用 --mixed 模式(默认)会移动当前分支的指向,并重置暂存区,但不会更改工作目录。使用 --hard 模式会完全重置当前分支的指向,并将工作目录和暂存区恢复为指定提交的状态。
  3. 影响协作

    • revert:适用于公共分支上的协作,因为它创建一个新的提交来撤销指定提交,不会影响其他人的工作。
    • reset:慎用在公共分支上,因为它会修改历史记录,可能导致其他人在分支上的工作丢失或冲突。
  4. 安全性

    • revert:较为安全,因为它创建一个新的提交来撤销指定提交,不会修改已有的提交记录。
    • reset:潜在风险较高,因为它会修改历史记录,可能导致数据丢失。使用前需谨慎考虑。 git revert 会依据选择的提交记录进行抵消

各类分支场景的解决方案

这一部分会结合各个可能在工作中遇到的场景,给出有效的解决方案,这边建议在看到场景和需求之后先自己实现一下(脑补也行)!千万不要怕麻烦,不然麻烦的就是工作中的自己😭!

场景一:分支合并

基准分支:release1.0

开发分支: featA、featB

分支情况:分支开发完毕,featB 有4个提交,featB 有2个提交

需求:release1.0 经过一次 bug 修复,现在需要将两分支合入release1.0

最简单的思路:逐个 merge,然后解冲突。这种逐个合并的方法相对简单直接,但可能比较耗时、复杂,尤其是在合并多个提交时。

因此我们可以使用 rebasecherry-pick 的方式来合并分分支:

  1. (featA) git rebse release1.0 将 featA 变基到 release1.0 上
  2. (featA) git cherry-pick featB-commit-1 featB-commit-2 将 featB 的两个提交
  3. 提 mr ------ featA 合入 release1.0

这边在第二点使用 cherry-pick 是考虑到 featB 的提交只有2个,比 rebase 4个提交要方便得多。

场景二:回滚提交

基准分支:release1.0

开发分支: featA 分支情况:分支开发完毕,featA 有2个提交,commit1 新增了功能1,commit2 新增了功能2

需求:将这一版本的功能1延期到 release1.1

此时我们就需要将 featA 的 commit1 进行回滚。 此处可能会想到使用 reset,但其实有个更好的方案: revert。
git revert 通过创建一个新的提交来撤销指定的提交(相互抵消)

因此我们可以直接通过 git revert commit1 来抵消第一次的提交。 ps:revert 与 reset 的比对会在下一部分详细说明。

场景三:最新提交的错误修复

基准分支:release1.0

开发分支: featA 分支情况:分支开发完毕,featA 有2个提交,commit1 新增了功能1,commit2 新增了功能2 需求:发现功能2还有缺陷,但不希望有新提交

此时的方案就是修改后,通过 git commit --amend 来合并分支,具体的步骤如下:

  1. 修改缺陷,git add -Agit commit --amend
  2. 根据情况改写 commit 的说明,保存提交
  3. git push --force-with-lease origin featA 强推提交

场景四:git stash 暂存记录

基准分支:release1.0

开发分支: featA 分支情况:分支开中 需求:开发到一半,工作区未提交,此时因为一些紧急需求需要切换分支

通过 git stash 可以轻松实现这个问题:

  1. git stash 将工作区内容储藏
  2. 切换分支,处理好问题后,切回分支
  3. git stash pop 将储藏的内容取回

当然还有一个解决思路:一个仓库拉两个项目,这个行为是十分推荐的,比如对构建工具进行升级,一些配置需要进行对比,拉两个对比新旧无疑是非常方便的选择~

场景五:重要分支被污染

这是本人在工作中遇到的一个场景,因为一时的疏忽,rebase 的分支选错了。背景有点长,先仔细看看:

基准分支:release1.0

开发分支: featA、release1.1

分支情况:分支需要集中于 release1.1 提测,featA 涉及到基建改动,提 mr (merge request) 时不希望被其他改动污染,因此切出 featA-backuprebase 1.1 后提交了 mr,此时 featA 需要再提一个 mr 基于 1.0 方便进行 code review

污染原因:提测一半发现有源自 featA 的 bug,在 featA 上修改后 rebase 了 1.1,切出新分支合入 1.1

仔细想想真的很粗心,本来应该从 featA 再切出一个新分支再 rebase 1.1 的,先后顺序的不一致导致了 featA mr 1.0code review 受到了影响。

这边是操作前后的分支情况图:

还好有 Git 大法!!!这边祭出我的解决方案:

  1. 可以看到 C3、C4 混进了 featA 的提交记录中,可以先通过 git reset C2清除后面的记录
  2. 切换到 featA-backup 分支,拿到 C5 的 commit 值,返回 featA
  3. 通过 git cherry-pick C5 将 C5 接入 C2 后,至此完成回退

其实还有另一种办法:

  1. git revert C3 C4,通过新的提交抵消 C3、C4
  2. git rebase -i HEAD~5 合并 C3、C4、C5、C3'、C4',等同于 C5

还有更多的场景会在后续逐步更新~

最后的最后

Git 的实际远远不止于此,在后续也会随着能力积累更新更多相关的文章出来。

面对工作中的 Git 问题,还是要熟能生巧,多查多练,期望能早早玩透 Git 大法🤓~

相关推荐
也无晴也无风雨31 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤5 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui