Git如何批量修改commit message

当你好不容易攒了十几个 commit 了,然后发现 push 上去的时候因为 commit 消息格式被卡。

如果只是一条 commit message 消息格式不对,我们知道可以使用

1
git commit --amend

命令来修改。可是如果连续十几条消息错了甚至几十条消息错了,该怎么一一修改呢?别怕,git rebase 来帮你。

首先,使用 git log 数一下有多少条消息出错了,假设有9条消息出错如下:

1
2
3
4
5
6
7
8
9
10
* cc136b48 - (2 hours ago) 马赛克9 (origin/main, main, HEAD)
* 0e4e4a30 - (2 hours ago) 马赛克8 - 梅世祺
* 4469b485 - (3 hours ago) 马赛克7
* f038110b - (6 hours ago) 马赛克6
* c4746347 - (6 hours ago) 马赛克5
* edbfc586 - (10 hours ago) 马赛克4
* 7a331663 - (3 days ago) 马赛克3
* ca754c4e - (3 days ago) 马赛克2
* 6f361bb8 - (3 days ago) 马赛克1
...
1
git rebase HEAD~9 -i

运行这个命令后,我们会进入交互式编辑页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
pick cc136b48 - (2 hours ago) 马赛克9 (origin/main, main, HEAD)
pick 0e4e4a30 - (2 hours ago) 马赛克8 - 梅世祺
pick 4469b485 - (3 hours ago) 马赛克7
pick f038110b - (6 hours ago) 马赛克6
pick c4746347 - (6 hours ago) 马赛克5
pick edbfc586 - (10 hours ago) 马赛克4
pick 7a331663 - (3 days ago) 马赛克3
pick ca754c4e - (3 days ago) 马赛克2
pick 6f361bb8 - (3 days ago) 马赛克1

# Rebase c4b63133..cc136b48 onto 0e4e4a30 (9 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.

我们把这些 commit 前面的 pick 全改成 e 即 edit 编辑后,保存。接着,HEAD 指针会移到这个位置:

1
2
3
4
5
6
7
8
9
10
* cc136b48 - (2 hours ago) 马赛克9 (origin/main, main)
* 0e4e4a30 - (2 hours ago) 马赛克8 - 梅世祺
* 4469b485 - (3 hours ago) 马赛克7
* f038110b - (6 hours ago) 马赛克6
* c4746347 - (6 hours ago) 马赛克5
* edbfc586 - (10 hours ago) 马赛克4
* 7a331663 - (3 days ago) 马赛克3
* ca754c4e - (3 days ago) 马赛克2
* 6f361bb8 - (3 days ago) 马赛克1 (HEAD)
...

接着 Git 会提示你

1
2
3
4
5
6
7
8
Stopped at 6f361bb8...  马赛克1
You can amend the commit now, with

git commit --amend

Once you are satisfied with your changes, run

git rebase --continue

即执行

1
git commit --amend

修改这个 commit 的 commit message,执行

1
git rebase --continue

进行下一步。 从最远的 commit 开始修改,一直到最近的 commit 直到修改成功。

当然这个方法也适用于修改一个旧 commit 的 commit message,我们只需要在 git rebase 的交互式编辑页,把想要修改的几个 commit 改成 edit,其他 commit 保持 pick 就可以了,步骤几乎一模一样。

参考资料

  1. How to Change a Git Commit Message

优化ZSH启动速度

我们经常在 ~/.zshrc 塞一堆自定义函数和 alsias、export 各种 path,导致 zsh 的启动时间长的让人难以忍受。

ZSH 提供了一个自动的性能分析工具 zsh/zprof 用于分析 zsh 启动时各组件或者说各脚本执行所占用的时间,使用方法如下:

编辑 ~/.zshrc 在配置文件首行插入 zmodload zsh/zprof,然后在最后一行插入 zprof

~/.zshrc
1
2
3
zmodload zsh/zprof
...
zprof

接着运行下面的命令来查看 zsh 启动时各组件占用的时间

1
time zsh -i -c exit

示例结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
> time zsh -i -c exit
num calls time self name
-----------------------------------------------------------------------------------
1) 1 29.04 29.04 30.43% 29.04 29.04 30.43% handle_completion_insecurities
2) 2 56.19 28.10 58.87% 28.38 14.19 29.74% compinit
3) 2 27.81 13.90 29.13% 27.81 13.90 29.13% compaudit
4) 2 8.18 4.09 8.57% 8.18 4.09 8.57% (anon)
5) 1 0.76 0.76 0.80% 0.76 0.76 0.80% colors
6) 3 0.40 0.13 0.42% 0.40 0.13 0.42% add-zsh-hook
7) 1 0.23 0.23 0.25% 0.23 0.23 0.25% is-at-least
8) 3 0.20 0.07 0.21% 0.20 0.07 0.21% compdef
9) 2 0.18 0.09 0.19% 0.18 0.09 0.19% wrap_clipboard_widgets
10) 5 0.17 0.03 0.18% 0.17 0.03 0.18% is_plugin
11) 1 0.04 0.04 0.04% 0.04 0.04 0.04% detect-clipboard
12) 2 0.03 0.01 0.03% 0.03 0.01 0.03% env_default
13) 1 0.02 0.02 0.02% 0.02 0.02 0.02% bashcompinit

-----------------------------------------------------------------------------------

2) 2 56.19 28.10 58.87% 28.38 14.19 29.74% compinit
1/2 27.81 27.81 29.13% 0.30 0.30 compaudit [3]

-----------------------------------------------------------------------------------

1) 1 29.04 29.04 30.43% 29.04 29.04 30.43% handle_completion_insecurities

-----------------------------------------------------------------------------------

1/2 27.81 27.81 29.13% 0.30 0.30 compinit [2]
1/2 27.51 27.51 28.82% 27.51 27.51 compaudit [3]
3) 2 27.81 13.90 29.13% 27.81 13.90 29.13% compaudit
1/2 27.51 27.51 28.82% 27.51 27.51 compaudit [3]

-----------------------------------------------------------------------------------

4) 2 8.18 4.09 8.57% 8.18 4.09 8.57% (anon)

-----------------------------------------------------------------------------------

5) 1 0.76 0.76 0.80% 0.76 0.76 0.80% colors

-----------------------------------------------------------------------------------

6) 3 0.40 0.13 0.42% 0.40 0.13 0.42% add-zsh-hook

-----------------------------------------------------------------------------------

7) 1 0.23 0.23 0.25% 0.23 0.23 0.25% is-at-least

-----------------------------------------------------------------------------------

8) 3 0.20 0.07 0.21% 0.20 0.07 0.21% compdef

-----------------------------------------------------------------------------------

9) 2 0.18 0.09 0.19% 0.18 0.09 0.19% wrap_clipboard_widgets

-----------------------------------------------------------------------------------

10) 5 0.17 0.03 0.18% 0.17 0.03 0.18% is_plugin

-----------------------------------------------------------------------------------

11) 1 0.04 0.04 0.04% 0.04 0.04 0.04% detect-clipboard

-----------------------------------------------------------------------------------

12) 2 0.03 0.01 0.03% 0.03 0.01 0.03% env_default

-----------------------------------------------------------------------------------

13) 1 0.02 0.02 0.02% 0.02 0.02 0.02% bashcompinit
zsh -i -c exit 0.10s user 0.06s system 95% cpu 0.165 total

启动时间只需 0.1s,好耶,这源于我替换了 nvm 为 fnm 的结果

参考资料

  1. Profiling zsh startup time

VSCode 执行 husky 钩子提示 command not found

提示找不到 npm 命令,但是在终端中执行就是好好的。说明 VSCode 执行的时候,没有执行 fnm 的初始化脚本:

~/.zshrc
1
2
3
# fnm
export PATH=/Users/lolimay/.fnm:$PATH
eval "`fnm env`"

解决办法

新建一个 ~/.huskyrc 配置文件,这其实是一个 husky 在执行真正的命令前执行的一个脚本文件。添加下面的内容

1
eval "`/usr/local/bin/fnm env`"

即,手动初始化 fnm,来帮助 sh 找到 node 和 npm 的路径。

如何从Sketch导出选中内容到SVG

错误示范

在左侧树状栏中右键选中图案,点击 Copy SVG Code。这种方式导出的 SVG 图片可能会与 Sketch 中的原图案出入较大。

正确示范

双击选中想要导出的图案,然后在菜单栏中找到并点击 Layer - Make Exportable

此时,页面右下角会有导出面板,选择导出格式为 svg 然后点击 Export Selected 即可正确导出图案为 SVG。

聊聊腾讯的跨端开源框架 Hippy

Hippy 简介

hippy /'hipi/

hippy的跨端方案思路和 React Native 一致,使用 v8 引擎执行 JavaScript 逻辑代码,使用原生组件的方式渲染UI以提升性能。但是hippy相较 React Native 而言,有以下优势:

1. 更轻量。更小的安装包、打出的JS bundle包体积也更小,只有React Native的一半左右。

2. 渲染性能比React Native 更好。

3. 和 Web 接近的开发体验。

    > Hippy 在开发体验上也进行了大量优化,包含但不限于,跟浏览器一样的 onClick、onTouch 系列触屏事件,更加简单的动画方案,hippy-vue 提供了和 Vue 的完全兼容等等。

    在开发体验这一点上,hippy也是远远优于React Native 的。后文介绍了hippy跨端原理,

为什么 hippy 可以跨端?

我们看看 hippy-react 和 hippy-vue 的架构图就明白了。

因为两者均支持 vDOM并支持自定义渲染器,hippy-react基于React 的React-Reconciler 实现了自定义渲染器,而 hippy-vue 基于 Vue 3 的 createRenderer() 实现自定义渲染器。

这其实也解释了为什么 hippy 到目前为止也只支持这两个前端框架,不支持 svelte 等其他框架。如果需要 hippy 支持一个前端框架,那么至少得让这个框架有自己的 vDOM 并支持第三方自定义渲染器去渲染它的 vDOM 组件节点树 。市面上也恰好只有 React 和 Vue 支持这些,并且技术相对比较成熟。

Hippy 作为 React Native 的后继者,同样基于 Facebook React 的官方自定义渲染器 react-reconciler 重新开发了 React 到终端的渲染层,可以使用React 的全部特性,在语法上和 React Native 类似,但更轻量、性能相对而言更好。

渲染中最重要的是什么——布局 (layout)。Facebook 为 React Native 用C++ 实现了 yoga 布局引擎。QQ浏览器团队也是比较厉害,参考了 chromium 中的布局引擎、Facebook 的 yoga 布局引擎硬是为 hippy 实现了自己的一套非常简洁的布局引擎 HippyLayout 。而且在开发中他们也是以 yoga 为性能基准,对 HippyLayout 进行性能调优的。

此处注意,yoga 和 HippyLayout 都是 Flex 布局引擎。这意味着,在一个 hippy 项目中,你应该尽可能地使用 flex 去实现布局需求(事实上,在我经手的大部分 Web 项目中,我都是 Flex 一把梭,基本可以解决80% 的布局需求)。

我们关心的几个问题

  1. hippy是不是同时支持ios和android?

    结论:既然是跨端框架,当然是都支持的。Android端集成文档iOS端集成文档

  1. hippy的定制化程度高不高,比如他的长列表标签里面是不是前端随便怎么写都行?

    结论:是的,可定制化程度非常高,甚至可以一个列表中渲染多种样式的列表项。

需要注意的点

1. 样式

    - Hippy 的所有样式支持由终端直接提供,基本和浏览器一致,但不支持百分比布局。目前Hippy支持具体数值,单位是 dp 。具体换算公式为:

        \(实际真机长度值 = 屏幕缩放比例 * Hippy 样式长度值\)

    - Hippy采用了CSS标准盒模型构建,对应的是 CSS 的box-sizing: border-box,这也意味着你不能在 Hippy 中通过修改 box-sizing 来修改 Hippy 盒模型的行为 (注:在浏览器CSS盒模型中, box-sizing 的默认值是 content-box )。

    - 使用 Flex布局。前面提到,Hippy用C++实现了自己的 Flex 布局引擎 HippyLayout。因为 Hippy 仅支持 Flex 布局,所以我们不需要在样式中手写 display: flex

    - Hippy 使用 CSS-in-JS 的方式编写样式,我们主要通过 @hippy/react 提供的 StyleSheet 类来统一管理组件的样式。

2. 动画

    由于 Hippy 替换掉了 Webkit 使用 vDOM 映射到原生 Native RenderPipeLine (原生渲染管线)的方式渲染界面。这意味很多 CSS 特性我们都不能使用,包括 CSS 动画。Hippy 动画的原理是由前端传入动画参数,由原生终端去控制每一帧的计算和排版更新,减少了前端与终端的通信次数,减少了动画的卡顿。

总结

得益于 React 和 Vue 的 vDOM 。采用 JSEngine + Native RenderPipeLine (JS 引擎负责执行通用业务主逻辑、原生渲染管线负责渲染界面),思路和 React Native 一致,

参考资料

  1. https://cloud.tencent.com/developer/article/1558201

  2. https://litslink.com/blog/new-react-native-architecture

  3. https://hippyjs.org/#/

  4. https://github.com/Tencent/Hippy

  5. https://blog.csdn.net/z4909801/article/details/88943851

  6. https://blog.csdn.net/wsyzxxn9/article/details/110161042

  7. https://zhuanlan.zhihu.com/p/107947462

  8. https://zhuanlan.zhihu.com/p/52459664

  9. https://www.bilibili.com/video/av37464898

  10. https://cloud.tencent.com/developer/article/1369800

  11. https://juejin.cn/post/6844904115462471693

酷狗小程序开启X5内核 Inspector 调试

酷狗小程序目前是采用x5内核渲染的,我们可以通过以下方式开启x5内核调试选项,然后使用 Chrome Devtools 远程调试以提升酷狗小程序的调试体验。

  1. 写一个最简单的酷狗小程序,调用下面的函数:
1
2
3
4
5
6
function() openDebugOptions() {
if (!window.MiniApp) {
throw new Error('MiniApp SDK 未初始化')
}
return window.MiniApp.navigateToHtmlPage({ url: 'http://debugtbs.qq.com' })
}
  1. 打开手机酷狗扫码打开这个小程序后进入 TBS 调试页

点击安装线上内核,重启小程序后再次进入点击查看版本信息,如果成功显示x5内核版本则说明x5内核已成功安装。

  1. 接着点击 Debug X5 进入X5内核调试选项配置页

最重要的是打开 信息 标签页,开启

  • 打开TBS内核Inspector调试功能
  • 打开TBS内核X5jscore Inspector调试功能

这两个选项。

其他配置项视自己需求开启,如 打开vConsole调试功能、渲染中的 内核网格线FPS meter 都是很有用的功能。

如果打开 FPS meter 显示字体是方框的话,可以开启 信息-关闭X5内核Custom Font功能 修复这个问题。

  1. 开启手机调试选项,使用USB连接电脑和手机,在 Chrome 地址栏输入 chrome://inspect 打开远程设备调试列表页

保持待调试的酷狗小程序在前台,开启 Discover USB devices 选项再刷新一下,这时候 Chrome 应该就可以发现这个小程序了。

如果设备显示已连接,但可调试页面列表一直为空,可以先打开 Android Chrome 再返回酷狗小程序,这样可以强制 Chrome 刷新列表。

  1. 点击 WebView in com.kugou.android 下面的 inspect 链接

注意,此步可能需要科学上网,因为 Chrome 需要去谷歌的网站下载适合这个 Webview 版本远程调试的 Chrome Devtools,否则会一直显示空白。

如果能成功打开 Chrome Devtools,那么后续的步骤就和使用 ChromeDevtools 正常调试一个桌面端网页的步骤一样了。我们可以使用 Element 查看 DOM 树和样式表,使用 Console 来查看日志,使用 Performance Monitor 来监控页面性能,进行针对性的优化,使用 JavaScript Profiler 来分析 JavaScript 虚拟机的执行情况。

MacOS信任自签证书

我厂一些内部网站使用了自签证书,但是自签证书在最新版本的 Chrome (Version 92.0.4515.59 beta) 上已经不被认可,无法打开这些网站。

实测使用 Firefox 仍可以访问,但是也需要展开高级选项才能打开。解决这个问题有两个方案,一个是使用 http 协议的链接去访问,另一个方案就是从系统层面信任这个证书。

下面简单介绍一下如何在系统层面信任一个自签证书的步骤:

导出证书

首先,使用 Chrome 打开目标网站,点击地址栏左侧的不安全的锁的图标,查看当前网站使用的证书,打开 Finder 在一侧备用:

按住 Option 键,长按证书图标拖到 Finder 中,接着这个证书会自动被保存为一个 pem 格式的证书文件:

导入并信任自签证书

打开,KeyChain Access 应用

点击右键左侧的 System Keychains -> System 选项卡,后右键点击 unlock 解锁当前系统证书配置

然后将 Finder 中的那个 pem 证书拖到证书列表中,双击证书列表中刚刚导入的自签证书:

选择总是信任后保存,重新锁定 System 证书配置。

检查

最后,我们打开原网址,点击 Advanced Options (高级选项) 按钮,点击仍要打开。之后,Chrome 就会记住你的选择,不会阻止你打开这类网站了。

唯一有点美中不足的是,Chrome 仍会在左上角显示不安全图标,如果不是强迫症的话就可以忽略了。

注意这种方法也是有弊端的,万一真的有一天这个网站的证书是被伪造了,由于你之前选择了总是信任该网站,所有不排除有一天你会打开钓鱼网站可能性。对于我个人的使用场景而言,由于这是公司的内网,选择总是信任该网站的证书没有太大的问题。

STM32驱动0.96寸OLED显示图片

  1. 将需要显示的图片(以jpeg格式为例)通过 convertio 转换为 bmp 格式;
  2. 打开 Windows 画图编辑图片,将图片缩放为 128x64 分辨率大小;
  3. 打开 搞定设计在线PS(photopea 中国版),点击菜单栏 图像->调整->阈值 可以在二值化过程中顺便去除噪点,保存成 bmp 格式;
  4. 打开取模工具 PCDtoLCD2002,导入第三步保存的 bmp 图片后预览效果。打开字模选项,按下图红圈方式设置后点击确定按钮保存设置,最后点击生成生成一个长度为 1024 的一维数组,复制备用;

  1. 粘贴下面代码到源文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const unsigned char images[1][1024] = {
{...你的图片...},
};

// 显示图片(通过改变索引值和图片对应的像素可以显示不同像素的图片)
// x,y: 图片的起点坐标
// px,py: 图片的像素(与实际取模的图片像素一致)
// index: 图片索引
void OLED_ShowBMP(u8 x, u8 y, u8 px, u8 py, u8 index, u8 mode)
{
u8 temp,t1;
u16 j,i;
u8 y0=y;

i = (px/2)*(py/4);

for(j = 0; j < i;j++)
{
temp = images[index][j]; //调用图片
for(t1=0;t1<8;t1++)
{
if(temp&0x80)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp<<= 1;
y++;
if((y-y0) == py)
{
y=y0;
x++;
break;
}
}
}
}
  1. 调用方法显示图片
1
2
OLED_ShowBMP(0, 0, 128, 64, 0, 1);
OLED_Refresh_Gram(); //更新显示到OLED
NOTES

如果你需要显示多张图片,可以把其它图片加到 images 数组中,然后在调用 OLED_ShowBMP 函数时注意指定 index 为相应的值即可。

参考资料

  1. 0.96寸OLED显示图片
  2. 怎样在Photoshop中二值化

怎么跑起来一个docker项目

用户反馈他们的应用不能正常发布,原因是线上编译器报错。我拿到用户的应用源文件后,本地测试可以正常编译部署。于是联系 Cloud 团队是否能提供 docker 镜像方便我复现线上环境,看看是不是环境问题。Cloud 团队负责人直接丢给我一个项目连接,打开后只有代码源文件和一个 Dockerfile 配置文件。

怎么从一个 Dockerfile 文件启动一个 docker 容器呢?

首先,我们构建 (build) 这个项目成一个镜像 (container image):

1
2
cd <project-folder> # 切换到项目根目录
docker build -t <image-name> . # 构成镜像

接着,我们就可以运行这个镜像了:

1
docker run <image-name>

修复ClashX HTTP代理端口和Socks5端口总是为0的问题

因为,ClashX 默认监听的是 7890 端口,怀疑是端口被占用了,我们使用 lsof 命令来查看端口被占用情况。

1
2
3
> lsof -i :7890
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
privoxy 579 lolimay 3u IPv4 0x527fa2f554e1edb 0t0 TCP localhost:7890 (LISTEN)

可以看到,端口被 privoxy 这个应用给占用了。接着我们用 ps 命令查看占用这个端口的进程。

1
2
3
> ps -ef | grep privoxy
UID PID PPID C STIME TTY TIME CMD
501 94421 1 0 10:43AM ?? 0:00.01 /Users/lolimay/Library/Application Support/ShadowsocksX-NG/privoxy --no-daemon privoxy.config

可以看到是 ShadowsocksX-NG 这个软件占用的,我们打开这个应用把它的监听端口改成 8790 或其他端口后,重启 ClashX 发现 ClashX 已经可以正常监听 7890 端口了 🎉