2025-07-10 21:59:21
Jujutsu(简称 jj)是一款功能强大的软件项目版本控制系统。你可以用它来获取代码副本,跟踪代码变更,最后发布这些变更供他人查看和使用。无论你是新手还是老手,无论你是独自开发全新的项目,还是拥有庞大历史和团队的大型软件项目,它都能让你轻松上手。
Jujutsu 目前基本可用,还缺乏少量功能,如 git submodule 的兼容、tag 的创建。
我会写一个系列的 Jujutsu 教程,这篇教程是本系列教程的第一篇,只讲一些满足日常操作的东西,学了本篇教程,日常就可以正常使用 Jujutsu 了。在使用 Jujutsu 的过程中,如果出了什么问题,优先看 Jujutsu 自己给的解决方案。
安装教程见 Jujutsu docs - Installation and setup,我用 Fedora,只能用 carogo-binstall 安装,用这个工具安装不需要从源码编译一遍,会直接从 GitHub 上下载已经编译好的二进制文件,并且 cargo-install-update 也支持通过这个工具更新安装的二进制文件。
无论你是从零开始,还是在现有 Git 仓库的基础上进行初始化,都推荐用下面这个命令:
|
|
该命令可以从
.git
初始化.jj
或者同时初始化.jj
和.git
。如果用jj init
初始化,会只有.jj
,但 Jujutsu 目前又无法从.jj
初始化.git
,用git init
自己手动初始化一个也没用,会没法从.jj
同步。Jujutsu 目前不支持创建 tag,如果要创建 tag,就要用到 Git,如果没有.git
,就会很抓狂,虽然可以解决,但要麻烦一点,别问,问就是踩坑了。
|
|
Jujutsu 中你不需要 提交(commit) ,但是需要 describe ,在仓库下做了一些改动后,或改动之前,或改动中,都可以用 describe 命令来解释改动,这个命令的简写是 desc:
|
|
Working copy 指的是当前正在工作的 copy,可以任意更改,如果是 Git 的话,如果要修改一个 commit,就要手动操作下,这就体现了 Jujutsu 的自动化。pwquumlq
是 Jujutsu 的 id,ae3142c8
是对应的 Git 的 id。在之后的操作中可以用 @
指代。
Parent commit 指的是上一个提交(父提交)。这里的 zzzzzzzz 00000000
说明父提交是 根(root) 。(empty)
表示这个 commit 是空的。(no description set)
表示这个 commit 没有 description。在之后的操作中可以用 @-
指代(多了一个减号)。
在终端中你会看到 zzzzzzzz
中的第一个 z
是高亮的,working copy 的 id 的第一个字母也是高亮的,高亮的字母 是 commit id 的简写,可以用来指代该 commit。直接高亮出来,方便很多,用终端操作的要比 GUI 快。
一个 commit 已经完成了,然后我们要移动到新的 working copy 进行接下来的工作:
|
|
或者你可以在改动完后把 describe
和 new
操作用 commit
命令一起完成,有多种方案,很灵活:
|
|
new
命令还可以从一个提交 分叉 出去,在用下面讲到的查看历史提交中就会看到分成了两条链:
|
|
可以直接运行 jj
来查看历史提交,相当于 jj log
,输出的结果会省略一部分提交,这里提交数量太少了,Jujutsu 不会省略:
|
|
这是省略的样子,(elided revisions)
会替代掉一部分提交:
|
|
查看完整的历史提交也是没问题的:
|
|
Jujutsu 中提交可以被轻松的编辑:
|
|
编辑完后回去:
|
|
是不是要比 Git 简单得多?
我们想要编辑的提交,往往都是父提交,例如忘了 format 或写错了一小点东西的时候,我们可以用 squash
更快的完成这步操作,这个命令是把当前 workng copy 的更改合并到父提交上:
|
|
运行完这行命令后,当前 working copy 就会变成空的,因为合并到了父提交中。
先加 remote,因为 Jujutsu 是与 Git 兼容的,所以可以直接推送到 Github 上,不需要 JJhub:
|
|
Jujutsu 中有 分支(Branch) 的平替概念—— 书签(Bookmark),但是书签一旦被 set,不会跟随当前的 working copy 的变动而改变,需要手动再次 set,才会变。
现在我们的仓库连 main 书签都没有,这个命令可以把书签 set 到当前 commit 上,如果不存在会自动创建。确保当前的 working copy 不是空的,如果是的话可以用 jj edit @-
编辑父提交,使当前的 working copy 变成父提交:
|
|
推送到远程仓库:
|
|
当对某个过去的提交更改后,推送是不需要加 –force 之类的参数的,爽了很多。
如果你不想要当前 working copy 的更改或最新的提交,可以抛弃掉:
|
|
注意:不要随意抛弃过去的提交,会导致冲突,很难处理,如果要合并过去的提交,可以用 squash
命令,这个命令更强大的用法将在下一篇教程中讲到。
当你后悔了一个操作的时候,就需要撤销,撤销操作也是非常的简单:
|
|
不是所有项目我们都会一律把提交 直接 推送到 main 分支上,按照 Github flow,至少要推送到其他分支上,然后发一个 PR 合并到 main 上。
只需要在推送到远程仓库的命令上多加几个字符就可以了:
|
|
这种方法推送上去的分支名是 push-[jj id]
,当然可以自己在本地先 set 了书签,然后再用 jj git push
推送。我比较懒不太喜欢给分支命名,因为 PR 名称就可以诠释一堆的提交是干什么的了,减少心智负担。
在同一个仓库里(多个维护者),如果每个人提交的都是默认的那种 push-[jj id]
,完全会乱套,我们可以把默认的分支名变成 yourname/push-[jj id]
这样去稍微做一点区分。编辑配置文件 .config/jj/config.toml
(用 jj config p
查看配置文件路径),加入以下内容:
|
|
远程仓库做了一些更改,需要把提交都拉取到本地仓库:
|
|
main 书签 set 的提交也自动变化了,但是通过运行 jj
你会看到当前 working copy 并不在 main 的那条链上,所以需要我们自己手动一下去移动到 main 那条链上:
|
|
用了一段时间的 Jujutsu 后,Jujutsu 基本已经平替了 Git,只能用一个字来说用的体验——爽。
虽然没有多少有价值的学习资料,边用边学的过程中,基本也用个会了,因为操作起来真的很简单。
下一篇教程会深入讲解 Jujutsu 的使用,敬请期待 :)
2025-06-09 19:50:11
之前看见一名推友说自己用 AI 结对写小说,发表到番茄小说上,遇到了没有流量的问题,番茄小说的一些规则其实它都写了,但要细品,不然怎么让你在上面发小说呢?
这里我就来梳理一下番茄小说写作的一些规则,可能都是我比较在意的。
年龄要求如下:
番茄必须要签约后才会对小说进行推荐,在签约前想要有流量,只能自己想办法引流。
没有了,我被挡在了签约条件第二条,发表的小说在签约前没有流量,我不知道值不值得签约,要是签约后不通过或是流量很差,我也没脸啊!会很后悔的!
审核似乎不是编辑在审,过不过审跟作品质量无关。审核速度非常快,快的话几分钟就过了(可怜勤勤恳恳的审核员…)。
番茄官方的作家助手 app 里是有 AI 助写的功能的,使用有限制,也应该是番茄的一种态度吧,大概能用,但是不要全用 AI 给写完了,即使过了审,如果被编辑或读者看出了,那就不好说会怎么样了。
这篇文章很短,我猜你点了进来,可能对你有帮助吧。后续是我准备试试知乎的盐选小说的水,看了下规则,好像审核非常严,是编辑在审稿,每次投稿都会多次审核,不知道写出来能不能。但是现在,我得马上赶作业了…
2025-04-30 22:31:56
很久很久之前写了一篇在 Linux 上如何把 Android 作为麦克风的教程,不久前因为要用 Windows 上的一些软件,装上了 Windows,顺便折腾个在 Windows 上的把 Android作为麦克风的方案。
找了很久,没有找到既方便又开源的方案,一些免费的方案(如 WO Mic)音质不太行,自己摸索了一方,最后用 Scrcpy 和 VB-CABLE 实现了。关键是 不需要在 Android 上安装任何软件!
使用 Scrcpy 把 Android 作为麦克风理论上在 Linux 和 macOS 上也可以,在音频驱动那里会有点不同。
确保 Android 版本 >= 11
首先是 Scrcpy,它将用于从 Android 转发音频,可以在 Github Release 页面 下载对应的压缩包再解压,32 位下载 scrcpy-win32-vX.X.zip
,64 位下载 scrcpy-win64-vX.X.zip
。
最好的办法是直接通过 Windows 的包管理器 winget 安装:
|
|
VB-CABLE 的用途是将音频由输出转到输入。
前往 VB-CABLE官网,点击 VBCABLE_Driver_Pack45.zip
下载压缩包,解压后,双击执行 VBCABLE_Setup_x64.exe
(64 位)或 VBCABLE_Setup.exe
(32 位)安装。然后就好了很么都不用动。系统 > 声音 > 输入 应该会自己变成 CABLE Output。
具体步骤见 Android Developer 文档。
如果通过压缩包获取 Scrcpy 点击解压后目录里的 open_a_terminal_here.bat
在该目录下打开终端。通过 winget 安装 Scrcpy 直接打开终端即可。
接着运行:
|
|
第一次运行 Android 上会要求授权,授权即可。
参数解释:
--no-video
不要画面--no-control
不要控制--audio-source=mic-unprocessed
将声音源指定为未处理的麦克风音频声音源还有很多选项,完整选项见 Audio 文档,我觉得 mic-unprocessed
音质是最好的,也可以试试别的,简单列举几个:
mic
: 捕获麦克风mic-unprocessed
: 捕获未处理(原始)的麦克风声音mic-camcorder
: 捕获为录制视频调优的麦克风声音,如果可用,其方向与摄像头相同mic-voice-recognition
: 捕获为语音识别调优的麦克风声音mic-voice-communication
: 捕获为语音通信调优的麦克风声音(例如,如果可用,它会利用回声消除或自动增益控制)在 系统 > 声音 > 音量合成器 > 应用 将 Scrcpy 创建的窗口的 输出设备 更改为 CABLE Input,现在通过 Android 麦克风输入的音频就不会从扬声器里输出了,会从输入设备 CABLE Output 里输出。
2025-02-16 11:08:28
Imagen 3 是 Google DeepMind 最新的文生图模型,可以在 ImageFx 免费使用。Imagen 3 在 Gemini 内也是可以使用的,Gemini 生成图片有时会不听话,不生成图片,所以本文采用 ImageFx。
主要有两种方式:
第一种方式 Imagen 3 不支持,本文就采用第二种。
想要有一个对人物描述相当详细的 Prompt,由人来写就太繁琐了,可以提供一些人物的特征让大语言模型帮我们写,这里采用 Gemini 2.0 Flash Thinking 模型。给出的特征越详细越能生成符合自己想要的人物。
示范 Prompt:
|
|
注:不要想着生成loli什么的,生成图片时会被判定为“儿童”而无法生成!
先用大语言模型写的 Prompt 生成一下,如果效果不错,把种子锁定下,最好把种子保存下,方便以后生成尽可能相似的人物。
下载一张图片,发给支持图像的大语言模型,并让它根据图像创造出详细的 Prompt。
示范 Prompt:
|
|
首先先生成一个生成人物坐在桌前写作业的图片的Prompt。
示范 Prompt:
|
|
我们将使用 [CHARACTER]
代指人物,然后把上一个步骤生成的 Prompt 拼接进去,如:
|
|
最终效果图:
2025-01-01 10:07:26
(封面来自 Unsplash,作者 BoliviaInteligente)
2024年结束了,2025年来了,转眼又是一年了。2024给我最大的震撼就是AI的辅助带来的便捷,过去稍有接触AI,但是没有太深入地使用,导致也用不好。
看到 X 上有很多大佬用 Cursor 开发出了一些项目,就有点手痒痒了。过去我使用的编辑器是 Helix,一个全键盘编辑器,感觉效率会高一些。如果要用 Cursor 这样的 AI 编辑器就要脱离全键盘的操作了,但是 AI 能提高我的开发效率的话,没有了全键盘操作也不算亏。于是 Cursor 就取代 Helix 在我的电脑上的地位。
Cursor 让我震撼的是,在编辑一块代码的时候,居然可以按 Tab 键去补全其他部分相关的代码,以前我以为 AI 代码补全就只能像补全变量名、函数名那样补全,这完全打破了我的认知啊!
最早使用 AI 我都倾向于想用一句话让 AI 完成我想要做的有点复杂的事,但在理论上是不可行的,事实上也是不行的。只用一句话去表述一件较为复杂的事,信息量很少,难以去描述细节,AI 自然无法做到和自己所想的相符。和人说件事,说话只说一句,得让对方多疯狂,更别说是 AI 了。在我的使用体验来说,AI 更适合去做小任务,而非是复杂的大任务,如果要让 AI 去做大任务,将它分解为多个小任务效果会更好。
AI 的使用体验总结起来就是一个字——“爽”,每周最多一天的时间里我可以开发得更高效。
2024年新开发的项目主要实在暑假里开发的,好几个我都觉得不太行,所以只挑出我最经常维护的词悦来说吧。
词悦是一个开源的支持 mdict 格式的词典,是我觉得 Android 上没有简洁、好用的开源的 mdict 词典而开发的。虽然最初发布的时候很简陋,不过现在经过几个月的开发,已经完善了许多了。
最初词悦用 git-cliff 生成版本发布时的更新日志,后来我才慢慢在词悦中把 Github 的 label、milestones 功能好好用上,现在词悦的版本更新日志是由 Github 生成的,这样可以把这个版本贡献者直接显示在更新日志中。
词悦还提交到了 F-Droid 上,我还提交过几个 MR,但是水平不太够,没办法,犯了很多低级错误,都由 linsui 大佬纠正了,感谢 linsui 大佬不知疲倦地修改我的 MR!
在开源中,我学会了许多以前不知道的技巧、技术,开源不仅利他,还能利己。
2024,我重启了我的博客,一年的文章就是2023的十几倍了(2023只有一篇文章)。2024我写了15篇博文,其中大部分都是在暑假写的。暑假闲来无事重启了博客,还把博客主题换成了 Stack。我还把博客提交到 V2EX VXNA、博友圈等平台上,我的博客也终于不再是我自娱自乐的地方了。
希望我可以在2025把 AI 使用得更加得心应手吧;希望我能在2025凭借自己的能力去赚到人生第一桶金,哪怕没几块也行哪。
2024-11-30 23:16:10
最近在开发词悦(一个 mdict 词典)的时候,需要支持全局上下文菜单,查了很多资料都没有找到合适的方法,问了下 cursor,得到了初步方案,经过稍微的改动就有了这篇教程。
本文开发环境在 Linux 下。
|
|
编辑 android/app/src/main/AndroidManifest.xml
:
|
|
创建 android/app/src/main/kotlin/com/example/example/ProcessTextActivity.kt
:
|
|
编辑 android/app/src/main/kotlin/com/example/example/MainActivity.kt
:
|
|
编辑 lib/main.dart
:
|
|
接下来怎么样就靠你的想象力了 :)