从手工导表到一键发布:我做了一个 Web 配置表 Git 管理器
一个运行在本机、通过浏览器操作的轻量级 Web Git 管理器。它不试图代替完整的 Git 客户端,而是围绕配置表发布这一条具体工作流,把最容易遗漏、最容易出错的步骤收进同一个界面。

文章目录8 个章节
因为某些不可抗力的原因,项目中我们采用了前后端共享配置表仓库和单分支多测试服务器的架构。这就导致了真正执行起来是一条很长的操作链:先在配置表仓库修改数据,运行 Luban 生成客户端或服务端文件;新增表格时还要额外执行建表脚本;然后根据目标环境进入不同的测试服仓库,再运行一次同步脚本,最后完成暂存、提交和推送。
任何一步被忘记,都可能让测试服拿到一份不完整的配置。更麻烦的是,这套流程每天都在重复,而每次重复都依赖操作者记住正确顺序。
为了解决这个问题,我实现了“小太阳配置表发布管理器”:一个运行在本机、通过浏览器操作的轻量级 Web Git 管理器。它不试图代替完整的 Git 客户端,而是围绕配置表发布这一条具体工作流,把最容易遗漏、最容易出错的步骤收进同一个界面。
一、先把真实工作流搬到一个页面
管理器只负责三个仓库:
- 配置表仓库
- 测试服 01 仓库
- 测试服 02 仓库
客户端仓库不在管理范围内,避免工具承担不必要的职责。三个区域使用统一的交互和功能,每个仓库都可以独立设置目录、SSH 私钥、自动同步和自动注释。
页面不再只展示一串 git status 文本,而是把工作区拆成“变更区”和“待提交区”,并按文件目录树显示。用户可以通过右键菜单完成:
- 将文件或整个目录加入待提交区
- 将文件移回变更区
- 放弃本地改动
- 使用 Beyond Compare 查看差异
- 在 Windows 资源管理器中定位文件
目录操作会级联到目录下的全部文件。提交按钮只在待提交区存在文件时启用,提交也只处理用户明确放入待提交区的内容。这让“我到底会提交哪些文件”变得非常直观。
二、自动同步不是简单地执行一个脚本
配置表仓库与测试服仓库使用不同的同步规则。
配置表仓库同步时,管理器会检查表定义文件是否发生变化。如果新增了表格,先执行 TableTool,再执行 Luban;普通数据修改则直接执行 Luban。测试服仓库只需要运行各自根目录下的 Luban 脚本。
每个仓库都有“提交前自动同步”开关。开启后,提交流程是:
- 记录当前待提交文件。
- 执行对应仓库的同步脚本。
- 同步失败时立即停止,不执行 commit,也不执行 push。
- 同步成功后重新暂存原先选择的文件,以包含脚本更新后的最终内容。
- 创建本地提交并推送到远程仓库。
这里有一个刻意保留的边界:同步脚本新生成的其他文件不会被自动加入待提交区。工具始终遵守“只提交用户明确选择的文件”,自动化不能以扩大提交范围为代价。
页面底部的“同步状态”入口集中展示三个仓库的执行结果。成功时显示绿色完成状态;失败时显示异常,并可打开完整日志定位问题。
三、让提交说明也自动化
除了忘记运行脚本,手写提交说明也是一项重复劳动。于是我在每个仓库的“提交说明”旁增加了“自动注释”开关。
开启后,管理器只分析 Git 暂存区,不读取尚未暂存的工作区改动。对于 Excel 文件,它直接解析 XLSX 内部的 ZIP/Open XML 数据,不依赖本机安装 Excel,并把每个工作表视为一张逻辑表:前四行作为字段结构,第五行开始作为数据。
最终可以生成这样的提交说明:
1.添加ActivityReward表格
2.删除OldShop表格
3.SkillBase表格字段结构及数据修改
4.VIPBase表格数据修改
生成器比较的是单元格坐标、值和公式,不会把光标位置、滚动位置、视图状态或文档保存时间误判为数据修改。同一张表同时发生字段与数据变化时,会合并为“字段结构及数据修改”。
提交前还会基于最终暂存快照重新生成一次说明。这样,即使自动同步更新了文件,提交说明仍然对应真正进入 commit 的版本。
四、检查更新、拉取和“最新版本”的区别
“检查更新”执行 git fetch --prune,只刷新远程跟踪分支,不修改本地工作区。远程存在新提交时,拉取按钮右上角显示蓝色数字徽标,数字代表本地落后的提交数量。

与此同时,远程改动文件会显示在页面底部“同步状态”弹窗对应的仓库区域中。列表只反映共同基线到远程分支之间的新增、修改、删除和重命名文件,不会混入本地工作区改动。
这也解释了一个常见误区:检查更新以后,Beyond Compare 仍然比较的是本地 Git 快照,而不是远程服务器上的最新文件。只有成功拉取后,本地 HEAD 才真正更新到远程版本。
五、冲突不能只显示一句“拉取失败”
管理器先 fetch,再根据分支关系选择拉取策略。本地无领先提交时始终使用 merge --ff-only;如果远程与本地修改路径重叠,只用带路径参数的 stash 临时保存交集文件,无关的本地 Excel 始终留在工作区。本地存在领先提交时才使用 rebase --autostash。冲突并不总以同一种形式出现:可能是 rebase 正在进行,也可能是远程更新已经应用完成,却在恢复选择性 stash 或 autostash 时发生冲突。
因此,后端会综合检查:
- Git 未合并文件列表
.git/rebase-merge与.git/rebase-apply状态CONFLICT、could not apply、Applying autostash resulted in conflicts等稳定输出标记
确认冲突后,页面打开专门的冲突弹窗。目前提供两个明确选项:
- 取消更新:尽可能恢复拉取前的本地状态
- 放弃冲突文件:仅让冲突列表中的文件采用远程版本,保留其他本地修改
“本地覆盖远程”没有实现,因为它涉及强制推送和更高的数据风险,不应该隐藏在一个轻易点击的按钮后面。
六、Windows 上最容易被忽略的问题:Excel 文件锁
真实环境中还遇到过另一类“看起来像 Git 错误、其实不是内容冲突”的故障:
error: unable to unlink old 'luban/Datas/Skill.xlsx': Invalid argument
fatal: could not reset --hard
在 Windows 上,如果 WPS、Excel 或其他程序独占了即将被替换的文件,Git 无法删除旧文件。直接执行拉取可能在更新到一半时才失败,现场比普通冲突更难恢复。
现在,管理器会在真正应用远程更新前分别计算远程、本地工作区和暂存区路径。fast-forward 路径只检查远程即将替换的文件,并只暂存远程/本地交集;rebase 路径会检查三类相关文件。只要当前策略需要替换的某个现有文件正被占用,就停止后续操作并列出具体路径。
此时 fetch 可能已经成功,所以蓝色徽标和远程文件列表可能已经刷新;但本地 HEAD、工作区、暂存区和 stash 都不会被改变。用户关闭对应文件以及可能驻留后台的 WPS/Excel 进程后,重新点击拉取即可。
打开一个与本次更新无关的仓库文件不会阻塞 fast-forward 拉取,也不会因为其他文件与远程重叠而被连带 stash。即使远程文件在预检通过后才被其他程序锁定,后端也会把随后的 unable to unlink old 重新归类为文件占用,而不是错误地弹出内容冲突处理。
七、本地 Web 应用的工程取舍
项目后端使用 ASP.NET Core Minimal API,前端使用原生 HTML、CSS 和 JavaScript。所有 Git、Luban 和外部工具调用都由后端启动本机进程完成,浏览器只负责发送结构化请求和呈现状态。
仓库目录和 SSH 私钥路径保存在浏览器本地存储中;私钥口令只保留在当前页面内存里,刷新页面后即消失。项目根目录的统一启动入口负责手动启动和开机自启:检查服务、隐藏启动、等待就绪并打开网页;开机配置写入当前 Windows 用户的启动项。
为了避免两个按钮同时修改同一个仓库,所有会改变仓库或远程状态的操作共享一个进程级操作锁。路径参数必须是仓库内的相对路径,后端规范化后再次校验,防止通过 .. 越过仓库边界。Git 参数通过 ProcessStartInfo.ArgumentList 传递,避免路径或提交说明中的空格被错误拆分。
这些设计并不华丽,但对于一个能执行 Git、脚本和外部程序的本地管理器来说,它们决定了工具是否值得信任。
八、这次改造带来的变化
这个项目最终解决的不是“做一个网页版 Git”,而是把一条依赖记忆的发布流程变成一条可观察、可中断、可追踪的操作链:
- 新增表格时自动补跑 TableTool
- 提交前自动运行正确的 Luban 脚本
- 同步失败时阻止提交和推送
- 精确控制进入提交的文件
- 自动识别表格字段和数据变化并生成说明
- 检查远程提交并展示具体改动文件
- 正确区分 Git 内容冲突、SSH 认证失败和 Windows 文件占用
- 在危险操作前保留清晰边界和恢复路径
自动化真正有价值的地方,不是把所有按钮合并成一个按钮,而是把每一步的前置条件、失败边界和结果都说清楚。对于配置表这种高频、跨仓库、容易遗漏的工作流,这种“有限但可靠”的工具,往往比一个功能庞大的通用客户端更合适。
下一阶段可以继续完善可恢复状态的持久化、逐文件冲突解决和更细粒度的发布审计。但在当前版本中,最核心的目标已经实现:让配置表从修改到测试服发布,不再依赖操作者完整记住那条长长的命令链。