!封面
如果你在一份法律意见书的工作文件夹里见过这样的文件名——
法律意见书_v1.docx
法律意见书_v2.docx
法律意见书_终稿.docx
法律意见书_终稿2.docx
法律意见书_真·终稿.docx
法律意见书_最终不改了.docx
那这篇文章就是写给你的。
这不是调侃。我自己做了十几年律师,太熟悉这套操作了——每次改一轮,另存为一个新文件,后缀越加越长。客户说"再改一版",整个文件夹又多出三个文件。过两周回来找"上一版改了什么",对着七八个文件名发呆。
程序员群体处理这个问题的方式完全不同。他们用一个叫 Git 的工具做版本管理,这套方法已经用了快二十年。本文不是要把你培养成程序员,而是告诉你:这个东西存在,它能干什么,以及怎么用你已经在用的 Claude Code 把它跑起来。
-
Git 是什么:一个"时间机器"
Git 是一个免费、开源的版本管理工具。安装很简单,去 git-scm.com 下载安装即可。装完后在终端里敲 git --version,如果能返回版本号,就说明装好了。
它的核心逻辑是"快照"——每次你觉得当前的文件状态值得保存,就做一次提交(commit),Git 会给此时此刻的所有文件拍一张"照片"并存档。这张照片不是覆盖上一张,而是独立存在的。你可以随时回到历史上的任意一张照片,看完之后再回到最新的那张,中间什么都不丢。
用过 Mac 的 Time Machine(时间机器)功能的话,差不多就是这个意思。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 200">
<rect width="600" height="200" fill="#fff" rx="4"/>
<text x="300" y="30" text-anchor="middle" font-size="16" font-weight="700" fill="#333">Git 的"时间机器"模型</text>
<!-- Timeline -->
<line x1="40" y1="100" x2="560" y2="100" stroke="#333" stroke-width="2"/>
<!-- Snapshots as dots and labels -->
<circle cx="80" cy="100" r="10" fill="#333"/>
<text x="80" y="80" text-anchor="middle" font-size="12" fill="#555">初稿</text>
<text x="80" y="130" text-anchor="middle" font-size="11" fill="#999">commit 1</text>
<circle cx="200" cy="100" r="10" fill="#333"/>
<text x="200" y="80" text-anchor="middle" font-size="12" fill="#555">增加了第三节</text>
<text x="200" y="130" text-anchor="middle" font-size="11" fill="#999">commit 2</text>
<circle cx="320" cy="100" r="10" fill="#333"/>
<text x="320" y="80" text-anchor="middle" font-size="12" fill="#555">根据客户意见修改</text>
<text x="320" y="130" text-anchor="middle" font-size="11" fill="#999">commit 3</text>
<circle cx="440" cy="100" r="12" fill="#fff" stroke="#333" stroke-width="2"/>
<text x="440" y="80" text-anchor="middle" font-size="12" fill="#555">当前版本</text>
<text x="440" y="130" text-anchor="middle" font-size="11" fill="#999">HEAD</text>
<circle cx="560" cy="100" r="6" fill="#999"/>
<text x="560" y="80" text-anchor="middle" font-size="11" fill="#999">未来…</text>
<!-- Arrow annotation -->
<text x="300" y="170" text-anchor="middle" font-size="12" fill="#888">可以随时回到任意一个快照,看完再跳回来</text>
</svg>
你现在可能用来做版本管理的东西,是 Claude Code 的"回退"功能——连按两次 ESC,或者在输入框旁边点那个向上的小箭头,就能回到之前的某一轮对话,同时把这轮对话产生的文件改动也还原回去。猛一看这好像也在做版本管理。
但它有三个致命缺陷:
第一,不能挑文件回退。 假设最后一轮对话改了三个文件,你只对其中一个文件的改动不满意。回退功能给你的选择是:要么三个全还原,要么全不还原。没有"只还原这一个文件"的选项。
第二,不能跨轮次自由跳转。 你聊了 30 轮,想回退到第 8 轮看看当时的状态。可以。但第 8 轮之后的 22 轮记录全部消失。你没法在第 8 轮看完之后再跳回第 29 轮——那条路已经断了。这跟 Git 的"随时跳、随便回"完全不是一回事。
第三,只管对话,不管外部工具。 如果 Claude Code 调用了你电脑上的某个 CLI 工具去修改了文件,这个改动 CloudCode 自己的回退功能是无法还原的。它只能回退大模型直接操作产生的结果。
这三条合起来,一句话:CloudCode 管的是对话,Git 管的是文件。不是一回事。
-
Git 怎么用:三个动作 + 一个概念
你不用学 Git 的命令行语法。你现在有 Claude Code,直接用自然语言说就行。
第一个动作:初始化。 在 VS Code 里打开你的工作区文件夹,对 Claude Code 说:
对当前工作区做 git 初始化
Claude Code 会在你的文件夹里创建一个隐藏的 .git 文件夹,从此这个文件夹就被 Git 管理起来了。你会立刻看到变化——文件管理器里,还没有被 Git 记录的文件名变成了绿色。
颜色的含义很简单:
- 绿色:新文件,还没被 Git 拍过照
- 红色:被删掉的文件,Git 发现它原来存在但现在没了
- 蓝色:重命名过的文件
这些颜色本身就是信息——你不需要打开文件就能知道工作区发生了什么变化。我实际用下来,最常用的反而是这个功能:跑完一个案件分析报告后,新生成的文件全是绿色的,一眼就找到了。
第二个动作:提交(commit)。 就是对 Claude Code 说:
提交当前工作区的所有改动,提交信息写"第一版法律意见书"
这就等于给当前的文件状态拍了一张快照。以后任何时候你都可以回到这个状态。
第三个动作:推送(push)。 把本地的快照传到 GitHub 上:
把当前工作区推送到我的 GitHub,新建一个仓库
这里引入了第二个概念——分支。分支就是你在主版本之外复制一份,在上面做实验。改坏了就扔掉这个分支,改好了就合并回主线。多人协作时特别有用:每个人各自开一个分支写自己的部分,最后一起合并。
对法律人来说,分支的典型场景是:某个诉讼策略的分析稿,你想尝试一种新思路但又怕把已有的分析搞乱。开个分支,在新分支上写,写完了看效果,不好就删掉分支,主版本毫发无伤。
-
GitHub:不止是代码仓库
Git 管的是你电脑上的本地版本,GitHub 是一个网站(github.com),管的是云端版本。两者的关系很简单:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 260">
<rect width="600" height="260" fill="#fff" rx="4"/>
<text x="300" y="28" text-anchor="middle" font-size="16" font-weight="700" fill="#333">工作区 → 本地仓库 → GitHub 远端仓库</text>
<!-- Working directory -->
<rect x="30" y="50" width="140" height="60" rx="3" fill="none" stroke="#333" stroke-width="1.5"/>
<text x="100" y="78" text-anchor="middle" font-size="13" fill="#333">工作区</text>
<text x="100" y="96" text-anchor="middle" font-size="11" fill="#999">你的文件夹</text>
<!-- Arrow: working dir to local repo -->
<line x1="170" y1="80" x2="230" y2="80" stroke="#333" stroke-width="1.5" marker-end="url(#arrow)"/>
<text x="200" y="72" text-anchor="middle" font-size="10" fill="#888">git init</text>
<text x="200" y="140" text-anchor="middle" font-size="10" fill="#888">git commit</text>
<!-- Local repo -->
<rect x="235" y="50" width="140" height="60" rx="3" fill="#f5f5f5" stroke="#333" stroke-width="1.5"/>
<text x="305" y="78" text-anchor="middle" font-size="13" fill="#333">本地仓库</text>
<text x="305" y="96" text-anchor="middle" font-size="11" fill="#999">.git 文件夹</text>
<!-- Arrow: local to remote -->
<line x1="375" y1="80" x2="435" y2="80" stroke="#333" stroke-width="1.5" marker-end="url(#arrow)"/>
<text x="405" y="72" text-anchor="middle" font-size="10" fill="#888">git push</text>
<text x="405" y="140" text-anchor="middle" font-size="10" fill="#888">git pull</text>
<!-- Remote repo -->
<rect x="440" y="50" width="140" height="60" rx="3" fill="#f9f9f9" stroke="#333" stroke-width="1.5" stroke-dasharray="4,2"/>
<text x="510" y="78" text-anchor="middle" font-size="13" fill="#333">GitHub 远端仓库</text>
<text x="510" y="96" text-anchor="middle" font-size="11" fill="#999">github.com</text>
<!-- Arrow definitions -->
<defs>
<marker id="arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">
<path d="M0,0 L8,4 L0,8 Z" fill="#333"/>
</marker>
</defs>
<!-- Bottom section: GitHub features -->
<line x1="30" y1="180" x2="570" y2="180" stroke="#ddd" stroke-width="1"/>
<rect x="30" y="195" width="160" height="45" rx="2" fill="#f5f5f5" stroke="#ccc" stroke-width="0.5"/>
<text x="110" y="215" text-anchor="middle" font-size="11" fill="#555">无限量云端存储</text>
<text x="110" y="232" text-anchor="middle" font-size="9" fill="#aaa">百度网盘不用买了</text>
<rect x="210" y="195" width="160" height="45" rx="2" fill="#f5f5f5" stroke="#ccc" stroke-width="0.5"/>
<text x="290" y="215" text-anchor="middle" font-size="11" fill="#555">GitHub Pages</text>
<text x="290" y="232" text-anchor="middle" font-size="9" fill="#aaa">免费建站·无需备案</text>
<rect x="390" y="195" width="160" height="45" rx="2" fill="#f5f5f5" stroke="#ccc" stroke-width="0.5"/>
<text x="470" y="215" text-anchor="middle" font-size="11" fill="#555">团队协同</text>
<text x="470" y="232" text-anchor="middle" font-size="9" fill="#aaa">添加合作者·多人编辑</text>
</svg>
对中国法律人来说,GitHub 有几个直接可用的点。
当无限量网盘用。 国内网盘要么限速要么限容量,GitHub 对单个仓库的大小限制非常宽松——我自己用到现在,从没碰到过容量不足的提示。工作成果、课程笔记、脚本工具,放上去就行了,免费,不限量。
免费建网站。 这就是 GitHub Pages。每个仓库都能变成一个可以直接访问的网页——不需要买服务器,不需要域名备案。你有网页文件(HTML),上传到仓库,在设置里点一下 Pages 部署,GitHub 就给你生成一个在线链接,复制给别人就能访问。给客户展示项目介绍、做临时活动页面、放个人作品集,全都可以零成本搞定。
全球最大的资源库。 GitHub 上不只有代码。有人上传了从小学到大学的整套教材 PDF,有律师事务所公开了合同模板库,有学者维护了法律条文变更的历史记录。有时候找一个冷门资料,百度和知网都搜不到,GitHub 上反而有人整理好了。
GitHub 的网址结构很简单:github.com/你的用户名/仓库名。每个仓库页面下面显示的那段介绍文字,来自仓库里的 README.md 文件。这个文件就是仓库的门面——你用 Claude Code 说一句"根据这个项目的情况写一个 README",它就能自动生成。
-
实操:从本地到云端,四句话搞定
假设你现在有一个工作区文件夹,里面有一些文件。你已经在 VS Code 左下角登录了 GitHub 账号(注册免费,去 github.com 花两分钟就能搞定)。然后你对 Claude Code 依次说下面四句话:
第一句:
对当前工作区做 git 初始化
第二句:
提交当前所有文件,提交信息写"初始版本"
第三句:
在当前工作区写一个 README.md 文件,简要介绍这个项目的内容和用途
第四句:
把当前工作区推送到我的 GitHub,新建一个仓库
说完这四句话,打开 github.com 刷新一下,新仓库已经在上面了,文件在、README 介绍也在。如果仓库设置里开启了 Pages 部署,网页也能访问了。
这整个过程,你没有敲过一行 git 命令。Claude Code 在背后帮你执行了 git init、git add、git commit、git push,你只需要用自然语言告诉它要干什么。
-
诚实说坑:Git 管不了 Word 文档的内容变化
这是一个我必须提前告诉你的局限,否则你用了以后会觉得"这玩意怎么跟说的不一样"。
Git 对纯文本文件(txt、md、html、json 等)可以做内容级的版本管理——改了一个字、删了一行、加了一段,都能精确记录。但对我们法律人最常用的办公三件套(docx、xlsx、pptx),Git 只能做文件级管理——它能告诉你"这个文件被修改过了",但改了哪里、改了什么,它看不到。
原因很简单:你把一个 Word 文档的后缀从 .docx 改成 .zip,然后解压,你会得到一个文件夹,里面是一堆 XML 文件。Word 文档本质上是压缩包,不是单一文本。你每次修改一个字,压缩包内部可能有多个 XML 文件同步发生变动,Git 没办法穿透压缩包去对比内容。
这就是为什么在四明山法师 AI 夜校的课程里,我们大量使用 markdown 格式。不仅因为 markdown 对 Git 友好、可以做内容级版本管理,更因为它对 AI 友好——同样的文字内容,markdown 输给大模型的 token 噪音远小于 Word 文档。对人和对机器,markdown 都是更干净的格式。
如果你需要管理 Word 文档的版本,目前更务实的做法还是保留文件名后缀的习惯,或者把关键内容同步一份 markdown 版本用 Git 管理。两者可以并行,不冲突。
-
一个容易被忽略的小操作:.gitignore
你的工作区里有些文件不应该上传到 GitHub——比如带密码的配置文件、带客户信息的 Excel 表格、带 API key 的脚本。
对 Claude Code 说一句:
以后工作区里所有包含密码、key、人名的文件都不要被 git 管理,也不要推送到 GitHub
它会在你的工作区根目录创建一个 .gitignore 文件,里面列明了哪些文件类型或文件名要被排除。Git 读到这个文件后,就会自动跳过它们——既不做版本管理,也不会上传到云端。
这是推送前的最后一道安全检查。如果忘了设,可能把你的敏感文件公开到互联网上。
-
法律人需要掌握到什么程度
你不必成为一个 Git 专家。程序员用了十几年还在查 Stack Overflow——这不是一个能"学完"的工具。
对法律人来说,知道下面这些就够了:
git init:让一个文件夹开始被版本管理git commit:给当前状态拍个快照git push:把本地快照传到 GitHub- GitHub Pages:免费部署一个可访问的网页
.gitignore:排除不该上传的文件- 办公文档(docx/xlsx/pptx)只能做文件级管理,不能做内容级 diff
更进一步的分支协同、Pull Request、代码审查流程,如果你不参与团队开发,暂时不需要碰。
-
版本管理是一种思维习惯,不只是工具。从前用文件名后缀,因为没有更轻量的办法。现在有了,每次提交就是一句话的事,想回哪就回哪。
Claude Code 帮你生成和修改文件,Git 追踪每一次变化的痕迹。两个东西配合起来,你的工作成果不再是一堆"终稿3"和"真·终稿",而是一条能往回走的路径。
这也是四明山法师 AI 夜校一直在做的事情——不是把法律人培养成程序员。就是让你知道那边有什么,挑趁手的拿过来用。
-
作者简介: 陈石律师,浙江海泰律师事务所副主任、高级合伙人、房地产与建设工程部主任,宁波市律师协会副秘书长、第七届宁波仲裁委员会仲裁员,聚焦建筑房地产、投融资、并购重组及商事争议解决。曾获多家法律媒体与专业机构认可,荣登 LegalOne 2025 中国区建工及房地产实务先锋 45 强、律新社 2025 年度管理合伙人 20 佳(华东),入选《商法》The A-List 法律精英,获评 ALB China 区域市场十五佳长三角地区律师新星,并获律新社 2024 年度并购领域品牌之星。长期为万科、华润置地、信达地产、保利置业、招商蛇口、中海地产等企业提供法律服务,承办"首宗百亿地王""长春第一高楼""台州第一高楼"等代表性项目,累计服务项目投资额超千亿。近年来持续推动 AI 与法律实务融合,强调以结构化方法打通技术逻辑、法律判断与商业场景;著有《赋能法律人:AI 底层思维与应用范式》,并在多地开展相关主题讲座与分享。四明山法师 AI 夜校(legalAGI.cn)发起人。