作者galic (嘎利)
看板Soft_Job
标题Re: [讨论] 零基础该懂 git 吗?
时间Tue Aug 4 22:57:09 2026
突然觉得值得回一篇,因为你在问的问题我最近才想过。
当然不是「有了AI之後,还需要 XXXX?」
这种换个 XXXX ,就能重新发一篇的格式废文。
我还顺便看了你在版上的其他文章,我觉得你其实有感受到真正的问题,
缺乏的是问出好问题的能力。
说的是
#1cUZCuPN (Soft_Job) [ptt.cc] [讨论] FP正在杀死设计模式吗?
零基础知识的 vibe coder 需不需要 git 我不知道,
但有基础知识的世界第一个 vibe coder → Linus Torvalds 就是发明 git 的人。
每个人工作的方式跟目的都不同,
你要论证这个题目可能得去找没 git 知识的初学 vibe coder,
分成两组:一组补充简单 git 概念,一组限制不能知道什麽是 git。
我相信最终你根本得不到什麽结论。
个人认为软体工程的直觉会破坏大脑的运作,
让你容易认定工作的结果跟工作的模式有直接关联。
你花大把的时间改善的只是效率或品质,(可能间接影响你能不能产出结果,)
但这跟是不是能走向预期的结果不是同一个问题。
这说的是你把使用工具的知识跟解答问题的知识绑在了一起,
如果能清楚的拆开,那这题根本不需要讨论。
直觉是一个简单判断条件:
如果产出结果必定需要某个工具,那使用工具的知识是必须的。
如果要开发 ios 程式是不是要学 swift?
如果要开发一个在 ios 上做健康管理的 app 是不是要学 swift?
很显然你问的问题很像後者,大部分的人会回答你健康管理的知识比学 swift更重要。
而今天,「学 swift」的位子可以用 AI 一词替上。「健康管理的知识」也可以。
这才是现在每个人都在面对的问题,而且他没有答案。
=====
其实想回答的是抽象语意的这题,这跟我最近在做的题目有关,
而我觉得我手上有你要的答案。
要先搞清楚的一点是 git 其实很复杂,这也是我一直觉得他很难使用的原因。
git 的底层实作是快照(snapshot),那是资料/资料库领域的东西。
但它的心智模型却是补丁(patch) 和增量。
最初我猜这原因来自:早期大家熟悉的版本控制都是补丁模型。但这好像没真正解释。
AI 给我的答案是因为分散式协作需要 Code Review 和 Branch (尤其是Long-lived)。
Code Review 需要的就是 diff △ (也就是patch),看看这次变更了哪里。
而 Branch 最终要 Merge 和 Rebase,你要解决冲突时也是 diff。
这观念最後影响了 Dolt — 把 Git 的增量概念套上了 SQL。
你推文举的 Jujutsu (jj/咒术) 很显然是在解我说的「git 很难用」的问题。
因为在 push 到 remote 之前,对我来说(或大部分不习惯多人协作的人),
patch 模型是杀鸡用牛刀。
没有 jj 之前,你需要 stash、rebase、cherry-pick 等高级操作。
而 jj 用的正好就是资料库的那套模型—ACID、Operation Log(Undo)...。
=====
最後你说的语意,那是第三种—CRDT 或 CvRDT。
这你平常就有在用但可能无感,Google Docs 和改版後的Notion。
他背後是一个漂亮的抽象代数—格(lattice),CRDT 是 join-semilattice (上半),
CvRDT 是 meet- (下半-)。
而格偏偏被用在词汇、命题、概念甚至程式状态,
利用格的偏序与上下确界结构,来对概念的包容、特异性与真值进行严格的数学建模。
你最熟的是指称语意,
说的是在 Domain Theory 中,熟悉的程式计算(Lambda Calculus) 被转换成完备格,
来证明递回、回圈语义是有意义且可收敛的。
所以语意的概念有了,版本控制有了,那一个(抽象)语意的版本控制是什麽?
这就是我在做的题目。
而我必须告诉你的是,他很可能必须是一种新的程式语言,因为现有语言很难做到。
一个贴近的语言叫 Unison,能做到基於语意的版控,
而他的实作叫做 Content-addressed AST(语法树)。
你需要能从语法层级... 不对。
这其实很简单:
res = create(
model="gpt-5.5",
instructions="分析这两个程式版本的差异?",
input=[ {"content": [file1 file2] } ],
)
print(res.text)
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 125.224.73.199 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1785855433.A.252.html
1F:→ MOONY135: ? 08/05 07:38
2F:→ sarsman: ? 08/05 09:04
3F:→ langrisser19: ? 08/05 09:32
4F:推 pponywong: 他其实就是想表示Linus才是第一个vibe coder 08/05 10:11
5F:→ pponywong: 只是vibe的对象是一群工程师 08/05 10:11
6F:推 GiPaPa: 我以为我很懂git 但现在我觉得我不懂了 08/05 10:14
7F:→ MOONY135: 我觉得他如果加上「token无料」 or 「token free」我会 08/05 10:41
8F:→ MOONY135: 赞成他的说法 免费的人力 08/05 10:41
9F:推 VScode: 你讲的东西好硬听不懂 08/05 13:21
10F:嘘 USD5566: 并不值得回一篇 他就上来问爽的 看个git而已在那边毛一 08/05 13:53
11F:→ USD5566: 堆被电还上来问可不可以不要看zzz 08/05 13:53
12F:推 abc0922001: 我也觉得奇怪,git不就是以防AI弄你吗 08/05 15:25
13F:推 viper9709: 推一二三楼~看不懂+1 XD 08/05 16:35
14F:推 wulouise: 同意问好问题的部分,其他太发散 08/05 18:21
15F:推 nashmvp: 推 08/06 00:54
16F:推 ian90911: 推 08/06 14:41
17F:→ Romulus: 我甚至第一次知道git底层实作是snapshot而不是patch 08/07 10:40
18F:→ Romulus: 这个version control based语言听起来很炫酷 发展的如何 08/07 10:41
回一下好了:
Unison 的内容定址想解的问题不是语意版本控制,他的重心在建置与重构。
因为名称改变杂凑不变,且依赖的是杂凑不是名称。
两个具有相同功能,仅变数命名不同的函式会被视为相同,这大大减少建置时间。
这被称作「渐进式编译与共用快取」。
起初看起来像是解效率问题,但这几年看起来更重要,因为他能有效防止供应链攻击。
但防不住命名/别名污染(像钓鱼攻击骗走你的签章),那是中心化套件发布系统的原罪。
19F:→ superpandal: 本来不想推文 推一下好了 首先git不是基於patch本来 08/07 20:28
20F:→ superpandal: 就是正常的 因为效能考量你不可能在基本版本一路套用 08/07 20:29
21F:→ superpandal: 变更再来比较差异 小repo还好大repo就不行 外部相容 08/07 20:31
22F:→ superpandal: diff和patch是跨版控工具或无版控的协作 release版本 08/07 20:33
23F:→ superpandal: 程式也不可能包含整个repo 至於git高级功能我是反对 08/07 20:38
24F:→ superpandal: 加入的 git本来就可以自定义指令 stash的功能大致上 08/07 20:40
25F:→ superpandal: 就只是git diff > 1.patch和git apply 1.patch的结合 08/07 20:41
26F:→ superpandal: 写个脚本就能有的功能 cherry-pick同理 rebase稍嫌麻 08/07 20:43
27F:→ superpandal: 烦 总之本来就是高度与系统机制整合与相容的工具 由 08/07 20:45
28F:→ superpandal: 此可知写一个好的东西条件压根不在於你读了多少指导 08/07 20:46
29F:→ superpandal: 性指南或算法 而是整合与一致性 环环相扣 扣人心弦 08/07 20:48
30F:→ superpandal: patch还可以修改套用 比stash灵活多了 至於语意版控 08/07 20:51
31F:→ superpandal: 我只能说近乎无意义 使用者如果都不想学git 你觉得他 08/07 20:53
32F:→ superpandal: 会去学你创的dsl 而那个dsl换用diff也才一行 你多写 08/07 20:54
33F:→ superpandal: 一大堆累赘 早就已经有很好的工具可以胜任 不多解释 08/07 21:03
34F:→ superpandal: 了 08/07 21:03
35F:→ superpandal: 至於sql的方式我觉得很丑 08/07 21:11
说到大部份的指令都是marco,补个可以做的练习。
git 主要物件只有内容(blob)、目录树(tree)和节点(commit)。
而多数时候你操作的都是指标: HEAD、branch、tag...,
和处理三个主要空间的同步: 工作区、暂存区(staged)、储存库(repo)。
先不管远端操作,设计一个 git 精简指令集会长怎样?
1. add [file]: 档案从工作区进入暂存区
2. snapshot: 档案从暂存区进到储存库 (类似commit但不移动指标)
3. point <name> <commit-id>: 操作指标,这个最难懂
<name> 放 branch name 就是 git branch
<name> 放 HEAD 就是 git checkout
<name> 放 branch name 但 <commit-id> 放 HEAD~2 之类的指标,就是 git reset
4. extract <commit-id>: 从储存库或暂存区取东西出来
5. diff <commit-A> <commit-B>: 产生 patch
-. apply: 把 patch 套用到工作区 (这不是git功能,所以不算)
说的练习就是自己组回原本的 git 指令:
commit = snapshot -> point HEAD + point branch
merge = apply (diff <parent> <current>) + (diff <parent> <target>)
-> add -> commit
rebase = (diff commit => patch) -> point <branch> <new-target>
-> extract -> apply patch -> add -> commit
stash = add -> snapshot (孤儿)
好像没练习到,因为我写出来了。
※ 编辑: galic (125.224.100.176 台湾), 08/07/2026 22:48:29
36F:→ superpandal: snapshot我不觉得有必要 apply怎麽不算git功能... 是 08/08 00:27
37F:→ superpandal: 可以不用git实现就是... 而底层操作根本不会曝露的 08/08 00:28
38F:→ superpandal: 不明白你发这个做什麽 我说的git自定义子命令是指可 08/08 00:30
39F:→ superpandal: 以新增子命令或修改曝露的子命令的运作 只要写脚本即 08/08 00:32
40F:→ superpandal: 可 而stash cherry-pick确实可以应用层透过脚本自己 08/08 00:34
41F:→ superpandal: 写一个 所以我认为这些子命令基本没必要实现 我相信 08/08 00:36
42F:→ superpandal: 原始版本的git都是简洁的 现在一大堆乱七八糟的 08/08 00:37
43F:→ galic: patch是unix指令... 08/08 00:55
44F:→ galic: 没snapshot要怎麽完成commit? 还子命令 你乾脆自己造个git 08/08 00:59
45F:→ galic: 这里是个分享知识和经验的学术论坛 至少我是这麽认为的 08/08 01:36
46F:→ superpandal: 我知道 我常用 但git apply是自己实现的 haha 08/08 01:41
47F:→ superpandal: 在commit内实现就可以了啊 不觉得一定得独立函数 08/08 01:43
48F:→ superpandal: git的子命令可以自己透过脚本扩充你不知道吗 本来就 08/08 01:44
49F:→ superpandal: 是这样用的 你举例的stash cherry-pick完全可以外部 08/08 01:45
50F:→ superpandal: 实现 我没有很想跟你讨论那麽深 刚开始回应就是了 只 08/08 01:48
51F:→ superpandal: 是多讲了一些 08/08 01:49
52F:→ superpandal: 因为你说那些是高级操作 我不那麽认为 我脚本仔凑的 08/08 01:52
53F:→ superpandal: 出来功能 事实上很多功能也应该这麽做 避免臃肿化 08/08 01:55
54F:嘘 pttano: 都不用懂 08/09 15:55
55F:→ galic: 自己跑到人家文章底下说写这些干嘛 你不自己认为自己发一篇 08/09 16:05
56F:→ galic: 不用拿你的蠢知识跟蠢用词来这里献丑 08/09 16:05
57F:→ galic: 在台湾 我们不说高级功能 我们说进阶功能 08/09 16:10
58F:→ galic: 我们不说指导性指南 我们说指引 08/09 16:10
59F:→ galic: 我们不说算法 我们说演算法 08/09 16:10
60F:→ galic: git的客制化指令是透过alias实现 那不是什麽鬼「子命令」 08/09 16:13
61F:→ galic: 那叫「别名」 08/09 16:13
62F:→ galic: git不建议自己组marco是因为你自己没办法处理「一致性」 08/09 16:15
63F:→ galic: 这里的一致性说的是资料一致性(data consistency) 08/09 16:16
64F:→ galic: 你没办法保证中间一个你乱组的指令错了之後是什麽结果 08/09 16:16
65F:→ galic: 你觉得人家设计太臃肿可以去给建议 但自己搞脚本就是走错路 08/09 16:18
66F:→ galic: 你厉害就自己造一个git让大家来佩服 08/09 16:18
67F:→ galic: 我在讲拆解精简指令有助於理解底层运作 你在那边扯东扯西 08/09 16:19
68F:→ superpandal: 高级操作是你讲的 我只是在附和你的说法 你要不要翻 08/09 18:38
69F:→ superpandal: 上去看你自己讲的 至於其它你管我讲什麽 我只是根据 08/09 18:40
70F:→ superpandal: 情况选词形容 这样一看你就是不懂怎麽客制化子命令 08/09 18:42
71F:→ superpandal: 还用git alias 完全就是不同东西 你在PATH下某个资料 08/09 18:45
72F:→ superpandal: 夹写个脚本名 git-test 再某个git repo 下执行 08/09 18:46
73F:→ superpandal: git test看看就知道了 还在扯git alias haha 我讲了 08/09 18:48
74F:→ superpandal: 系统机制你是完全不能领会关联 剩下你回应的就不用说 08/09 18:49
75F:→ superpandal: 了 完全建立在错误认知上 git本来就允许你这麽做 本 08/09 18:51
76F:→ superpandal: 来git就不需要提供太多的子命令 可以用扩充的 对应你 08/09 18:53
77F:→ superpandal: 你讲需要这些高级操作才能实现 你懂我的意思了吗 08/09 18:55
78F:→ superpandal: haha ai都比你好沟通 08/09 18:55
79F:→ superpandal: 还有 git有些子命令就是用脚本写的 连开发者都走错路 08/09 20:10
80F:→ superpandal: 了吗? 不要小看脚本 脚本开发便捷是很好的工具 08/09 20:13