ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

程序员如何处理烂尾项目:用Git归档与复盘未完成作品

程序员如何处理烂尾项目:用Git归档与复盘未完成作品 这次我们来看一个不需要安装、不需要显卡、不需要跑模型的技术问题Ask HN: What are your unfinished projects? 如果你经常逛 Hacker News会发现 Ask HN 栏目里每隔一段时间就会有人发起这类讨论代码库里躺着多少没写完的 Side Project那些停在 80% 状态的项目最后是被删除、被放弃还是被重新捡起来这不是一个能解压即用的开源工具但它在开发者社区里的价值不低。问题的本质是让程序员公开复盘自己“为什么没做完”。有人会把项目定义为技术验证有人会承认是自己中途迷失了方向也有人只是需要一个简单的答案遇到这种情况应该怎么收场。这篇文章会把 HN 式提问改造成一套可执行的项目盘点流程。你不需要特殊的硬件环境只需要 Git、终端、一个 Markdown 编辑器和一份诚实的心态。读完你能做的事很明确给未完成项目贴状态标签判断它值不值得继续用 README 和 Git Tag 完成归档写清停止原因与后续入口同时给自己下一次开新坑设好防烂尾边界。适合那些 Side Project 积压已久、想清理 GitHub 仓库、准备整理作品集或者单纯想减少“开坑一时爽填坑火葬场”情况的开发者。1. Ask HN 式话题能给什么能力速览与适用读者项目类型开发者个人项目复盘与归档不是软件工具核心问题Side Project 为什么停在未完成状态应该怎么收尾主要产出项目状态标签、判断决策表、README 归档模板、Git 收尾记录准备环境Git、终端、Python 3可选、代码编辑器适用读者清理仓库的开发者、有项目搁置经验的人、准备面试作品集的人不涉及商业付费项目的交付管理、需要上线止损的紧急项目这个“能力速览”和传统软件工具不太一样。它不提供一键部署也不提供 WebUI但它能帮你在一个小时以内把一个长期没动的仓库变成一份清晰的技术档案。很多开发者对自己全部项目并没有完整清单通常只记得最近写过的两个剩下的散落在 GitHub 私有仓库、本地目录、旧电脑和同事的 GitLab 里。先做盘点往往比继续写新代码更有价值。Hacker News 上的“Ask HN”是一种固定提问方式任何注册用户都可以用这个前缀发起开放式讨论。这类帖子的质量通常不在问题本身而在评论区。有人会讲自己做了一个半成品后如何从中学到架构设计有人会承认自己过度设计把工具型项目写成了框架也有人会展示那些被放弃但后来变成了写作素材、面试案例或者新项目前置验证的代码。它们本质上是在交换“什么时候该停怎么停得干净”的经验。技术工程里多的是“能跑但没完成”的项目。真正稀缺的信息不是“这个项目做出来了”而是“为什么没做出来”和“做了一半怎么处理”。这篇文章就是要把 HN 评论区里那些分散的经验整理成你自己就能复用的执行流程。2. 未完成项目的适用场景与使用边界2.1 这套方法适合解决的问题先给下面的场景对号入座。第一类你准备清理 GitHub 仓库。个人主页上有十几个项目其中一半最后一次提交停在两年前有的一直是 Private连 README 都没写。这时候你需要一个快速工具判断哪些项目直接删除哪些应该补一个“归档说明”再保存。第二类你正在整理作品集或简历。不少公司会看候选人的 GitHub 或技术博客半成品项目如果没有任何上下文面试官只会看到一个“没有做完”的仓库。反过来如果仓库里清楚写着“此项目完成了技术验证因维护成本过高暂停”并且有架构说明、运行方式、停止原因面试观感会好很多。第三类你希望建立长期维护的技术仓库但总是不知道哪些项目已经“死”透了。你可以给每个项目打状态标签比如active、paused、archived、dead然后定期跑一次盘点脚本检查最近提交时间避免项目在没人维护的情况下继续对外暴露。第四类你打算重启某个老项目但不确定到底值不值得。先做归档型复盘把当时的背景、目标、技术选型和卡点写清楚再决定要不要进入新阶段。2.2 不应该被当成“未完成项目”的场景有些情况不适合用这套归档心态处理。最常见的反例是客户付费项目。你已经收了钱项目延期和暂停就不是个人兴趣问题而是契约问题。这时候应该走正式的项目管理流程而不是清点完仓库然后写一个“暂停原因”就结束。还有一类是已经进入上线前兆、离发布只差一两个任务的项目。这种项目不要归档建议集中精力把最后一个功能砍掉先发布。未完成项目的最大误区是把“追求完美”包装成“暂时搁置”。如果你只是因为害怕公开测试、害怕差评而不发布那你需要的不是归档方案而是发布检查清单。另一个边界是隐私和授权。如果你归档的是包含业务数据的内部系统、包含客户信息的运营后台或者包含别人代码的二次开发项目不要直接把仓库推到公开平台。归档前先检查.env文件、密钥、Token、数据库连接串和第三方字体、图片、开源代码的许可证。公开一个半成品没有错公开一个带密钥的半成品就很麻烦。3. 项目为什么会停在 80%典型烂尾模式分析3.1 学习型 Demo 停在“跑通之后”有一类项目从一开始就不是为了交付而是为了回答“这个东西能不能实现”。你研究了一个新框架、一个新 API、一个新模型然后写了一个最小 Demo成功跑出一次结果后兴趣就消失了。这个问题很普遍。Demo 项目的准确状态应该是done而不是unfinished但很多人没有意识到它已经完成了当初的目标一直把它当成没做完的东西放在列表里吃灰。如果你能把这个区别讲清楚复盘价值会高很多。重点是记录我当初要验证什么假设是否有结论结论是什么。例如“验证 ComfyUI 的 API 是否能批量出图”结论是“可以但显存和队列稳定性是瓶颈”。这已经是一个完整的项目不需要补产品界面。3.2 工具型项目死在“维护成本”很多开发者的第一个成熟 Side Project 是给自己做的小工具。自己用得很顺手后来想分享给其他人才发现需要做文档、做跨平台兼容、处理不同环境的依赖安装于是一旦收到几个 GitHub Issue就被维护成本劝退。工具型项目烂尾往往不是编程能力问题而是没有提前定义维护边界。如果你学会给工具项目画一条线比如“只支持自己的系统环境”“只接受代码 MR 不回答使用问题”“不接受新功能需求”项目就能以开源但低维护的方式继续存在。归档时不要去补一堆功能而要把“维护边界”写清楚。3.3 集成型项目死在外部依赖变动这类项目在程序员群体里尤其多。你做了一个基于第三方 API 的服务结果上游接口变更你的解析逻辑全部失效你做了一个开源的模型调用管线结果模型权重更新所有超参数都不再适用你用一个 SaaS 服务的免费额度做了 Demo结果免费额度调整整个项目失去了运行前提。如果遇到这类情况不要急着责备自己“没有持续跟进”。很多外部依赖本身就处于快速变动状态个人项目根本追不上。归档时额外记录一个字段非常重要上游依赖的版本、许可证、接口文档地址、以及它在我项目里承担的职责。以后想重启能找回上下文才是关键。3.4 完美主义型项目死在“重写第三次”每次看都觉得架构不够好于是一次次重构却没有给用户交付任何稳定版本。这类项目最需要的是一个“冻结”命令。把当前目录复制一份标记日期然后告诉自己下一版必须基于这个版本而不是从零开始再花三周重写框架。4. 判断项目是暂停还是放弃给出明确结论当你在面对一个未完成项目时最忌讳的决策方式是“感觉它还有救先留着”。你不需要立刻决定是继续做完还是删除而是要先把项目归类。可以给每个项目贴一个状态标签状态标签含义后续动作active正在持续开发和维护正常提交保留在活跃目录stalled暂停开发但未来可能重启补好 README记录重启条件archived不再开发作为历史仓库保留补归档说明打 Git Tag移入归档目录dead已无存在价值项目不再保留清理并删除或转为私有仓库实际决策时可以结合三个判断维度。判断维度一这个项目还有没有“唯一价值”。如果一个项目能做的事现在已经有一键安装的开源方案、有更成熟的商业服务、有更好的模型替代那它的代码价值就明显下降。除非它能满足你学习底层原理的需求否则更适合归档而不是继续开发。判断维度二项目本身的健康度如何。打开仓库检查依赖是否过时、安全漏洞有多少、能否在新环境运行。如果依赖已经老旧到需要做一次全面升级那么重启成本并不低。做一个简单判断重启要花一周还是只要一小时。超出一周其实已经变成全新项目。判断维度三你的兴趣和精力是否还在。这一点很现实。做 Side Project 最重要的驱动是真实关注如果项目涉及的技术你已经没兴趣了硬撑出来的概率很低。这时候更合理的动作是“记录收获然后归档”而不是用意志力对抗需求。判断结果通常有两种。第一种是“值得重启”那你应该把它当新项目处理重新做需求拆分留出具体时间不要靠模糊的热情启动。第二种是“值得归档”那就直接进入下一步用 Git 命令和 README 把它变成一笔可读资产。5. 收尾归档让未完成项目变成可读技术资产5.1 建立项目目录结构建议先在本地建一个archived-projects目录把所有暂停和归档的项目集中起来。这样你可以定期浏览也不会让未完成项目继续占用工作目录里的注意力。# 示例目录结构 ~/projects/ active/ current-project/ archived/ old-sandbox-project/如果你还没有把项目纳入 Git 管理可以先执行下面的命令。注意路径需要按你的真实情况替换。cd ~/projects/archived/old-sandbox-project git init git add . git commit -m chore: archive snapshot before pause理想情况下每个 Side Project 在你开始写第一行代码时就应该有 Git 仓库这样最近提交记录、分支历史和撤销点都会保留。如果项目之前没有版本管理现在补上也不晚。先整体提交一次作为归档基线。5.2 写一份“归档态 README”归档后的项目最需要的信息不是功能说明而是上下文。你可以在 README 顶部放一个状态区块。模板如下# old-sandbox-project 状态: archived 最后维护: 2025-04 暂停原因: 依赖的第三方 API 已变更维护成本高于使用频率 当前结论: 已完成技术验证后续不再新增功能 ## 当时要解决的问题 一句话写明项目动机。 ## 技术方案 框架、语言、核心依赖、部署方式。 ## 做到什么程度 已实现功能、未实现功能、卡在哪一步。 ## 如果继续下一步是什么 给未来的自己留入口列出最可能的三个方向。这份 README 不要求很长但必须有“写给未来会打开仓库的人看”的意识。很多项目光看代码根本看不懂因为写代码时的思路早就随着时间丢了。README 的价值就是对抗这种遗忘。5.3 用 Git Tag 打一个状态节点单单写 README 还不够在 Git 里打 Tag 是更专业的收尾方式。无论以后你使用git checkout tag还是平台上的 Release 功能都能一眼找到归档版本。# 提交归档说明后打标签日期写当天 git add README.md git commit -m docs: add archive note git tag archive-2025-04-12这样的好处是即使你以后在这个项目上继续开发也不会丢失“归档那一刻”的代码状态。Tag 是只读快照不会随着后续提交移动。5.4 记录“如果再继续我会怎么做”这一步容易被忽略但价值最高。归档不是把项目扔进垃圾桶而是把你的技术判断放入仓库。比如你发现当前方案某处设计错了现在就记录如果你觉得某个功能完全可以删除也记录。未来的你打开这个仓库时如果只能看到代码大概率还是会犯同一个错误。可以把这些判断放在 README 的“If continuing”区块也可以单独写一份NOTES.md。写的时候不用追求格式重点是记录因果关系我遇到了什么问题我尝试了什么方案为什么最后决定暂停。6. 用脚本盘点所有项目的活性当项目数量变多后靠脑子和文件管理器去定位未完成项目已经不现实。可以写一个小脚本扫描项目目录找出每个 Git 仓库最后提交时间导出成 CSV。这个脚本不限定某种框架也不需要安装额外包只依赖 Python 标准库。import csv import subprocess import sys from pathlib import Path def last_commit(repo_path): try: result subprocess.run( [git, log, -1, --format%ad, --dateshort], cwdrepo_path, capture_outputTrue, textTrue, timeout10, ) return result.stdout.strip() except Exception: return unknown def main(): if len(sys.argv) 2: print(用法: python inventory.py 项目根目录) return root Path(sys.argv[1]).expanduser() if not root.exists(): print(目录不存在:, root) return rows [] # 只扫描根目录下的一级目录深层次扫描可按需递归 for child in root.iterdir(): if child.is_dir() and (child / .git).exists(): rows.append({ project: child.name, last_commit: last_commit(child), }) rows.sort(keylambda x: x[last_commit], reverseTrue) with open(project_inventory.csv, w, newline, encodingutf-8) as f: writer csv.DictWriter(f, fieldnames[project, last_commit]) writer.writeheader() writer.writerows(rows) print(f扫描完成共 {len(rows)} 个 Git 仓库) print(结果已写入 project_inventory.csv) if __name__ __main__: main()运行方式python inventory.py ~/projects/扫描完成后你会得到一份按最后提交时间排序的项目清单。那些最后提交日期停在一年以前的仓库就是你需要重点决定“暂停、归档还是删除”的对象。如果你希望支持递归扫描子目录可以用root.rglob(.git)替代一级目录遍历。扩展方向还可以是把每个项目的状态标签读出来或者统计每个仓库的代码行数和 Commit 数。这个脚本的价值不在于算法复杂而在于让“项目清理”变成一个可重复执行的动作。你不需要每次回忆自己还有哪些项目只要定期跑一次脚本结合 CSV 判断即可。7. 如何避免下一个项目停在 90%“未完成项目”这个话题真正扎心的地方在于处理完旧项目后你又很容易开一个新坑然后继续停在 90%。所以归档旧项目之外还要建立一套防停滞机制。7.1 先写“完成标准”再写第一行代码很多人立项时只会写“我要做一个视频下载工具”但不会定义“什么状态算完成”。因此项目会无限膨胀下载功能做完后想加转码转码做完后想加字幕字幕做完后又想加 GUI。更有效的做法是在项目根目录建一个SCOPE.md或直接写进 README## 完成标准 1. 能输入一个视频 URL返回 MP4 文件 2. 支持 1080p 清晰度下载 3. 支持批量导入 10 个 URL 4. 命令行界面可以完成操作不需要图形界面 ## 非目标 不处理用户登录不支持平台直播流不开发 Web 管理界面。“非目标”和“完成标准”一样重要。明确不做什么项目才不会被新增想法拖垮。第一次写项目时尤其要守住凡是“完成标准”之外的新需求必须单独记录到 backlog 里而不是立刻在当前实现中插入。7.2 给每个阶段设置退出条件Side Project 失败的一大原因是没有节奏。你只有周末零碎时间却给项目设定了每天推进任务的节奏两周后发现时间不够就自然停滞了。可以基于里程碑来管理阶段一实现最小闭环阶段二做基本稳定阶段三做性能优化。如果项目在阶段一通过后你判断阶段二的成本过高那就带着“已验证最小闭环”去归档。这种退出条件是主动决策不是被动烂尾。7.3 用“时间盒”替代“以后再说”当你想做一件事而又没把握时可以先开一个时间盒接下来两周每周只允许投入 3 小时。时间到了必须做一个阶段汇报项目继续、暂停、删除三选一。这样做的好处是避免项目长期挂在“进行中”但没有实质进展。即使暂停你留下的也是明确判断。7.4 让外部用户尽早参与Side Project 最好的防烂尾手段是有真实用户或者至少有一个目的明确的测试者。把自己写的工具发到一个相关社区收集两个反馈再决定是否继续开发。项目一旦有了外部使用者你对“完成”的定义就会清晰很多。大部分烂尾不是因为技术能力不行而是因为没有一个人真正等待结果所以推进动力会快速消失。8. 把搁置项目转化为作品集和面试素材未完成项目并非没有价值。面试技术岗位的时候完整展示一个“从问题分析到暂停决策”的项目往往比包装一个“从未上线但看起来全功能”的项目更有说服力。前提是你要能讲清楚技术脉络。面试官看到你的 GitHub 仓库时如果看到一个干净的状态标记和归档说明他可以很快判断这个开发者的项目组织能力不错知道自己停在哪。反过来如果仓库里只有代码和几次无说明的提交他会认为你甚至没有花时间整理。可以按这样的逻辑去描述一个未完成项目技术背景当时想解决什么问题为什么需要自己写而不是直接用现成方案。这能体现你了解生态而不是为了造轮子而造轮子。 技术选型项目采用什么语言、框架、数据存储、部署方式并解释取舍。比如选 Python 因为生态更适合做数据处理选 SQLite 因为个人项目不需要独立数据库。 进展与卡点项目做完了哪些模块哪些场景没有覆盖卡在了什么地方。例如外部 API 授权获取困难、复杂业务规则导致边界情况爆炸、或者性能无法达到预期。 停止原因不要只说“没时间”要说清楚判断依据。例如验证了某个核心假设不成立或者维护成本已经超过项目本身带来的价值这是一种工程判断。 提取经验你从中学到了什么下一次会怎么做。这个部分最能展示成长性。这套描述逻辑不只适用于作品集也适用于写博客或者复盘。把一个项目从“烂尾”变成“有结论的项目”关键一步是给自己一个技术判断而不是一句“后来太忙了”。9. 常见决策误区和心理阻力误区表现更合理的处理方式沉没成本绑架因为已经写了三个月所以不想删除问自己如果这个项目今天从来没写过我还会开始吗害怕公开半成品项目不发布也不归档一直躺在本地先写归档 README再选择 private 或 public重写冲动因为旧代码不够好想推倒重来先量化旧代码中可复用的部分只重写真正烂掉的核心惯性收藏凡是 GitHub 上看到的项目都想自己做一遍给自己设置一个“同时最多两个 Side Project”的上限决策模糊项目既不启动也不归档拖了半年用状态标签强制归类没有“等以后再说”外部验证缺失做完以后不发不测自己也不知道好不好用先丢给身边一个人用观察他能否独立完成操作这里最值得单独说的是“沉没成本”问题。很多程序员强迫自己继续一个项目并不是因为项目仍值得做而是因为不想承认前期投入浪费了。技术决策里已经写过的代码天然会让人产生依赖你越熟悉它越觉得它有救。但判断项目价值的正确方式从来不是看已经投入多少而是看未来还要投入多少、能得到什么结果。如果你发现自己不敢打开一个旧仓库总在潜意识里回避它这本身就是一种信号。更好的选择不是强迫自己继续而是给自己一个快速收尾任务花十五分钟把项目的 README 写好打个 Tag推到 GitHub 或者移到归档目录。任务完成后你会明显感觉到心理压力变小因为项目终于有了一个清晰状态。10. 总结与下一步行动“Ask HN: What are your unfinished projects?” 看起来只是一句社区提问但它值得你在本地落地成一套小流程。程序员每天面对大量未完成的技术探索这不是个人自律问题而是信息管理问题。项目的状态如果不被记录就会被遗忘一段时间后你连它到底想解决什么问题都不知道。这篇文章建议你先做的事只有一件在今天结束时挑一个你最常想起又一直没动的旧项目给它在本地补一份归档 README写清楚当时要做什么、做到了什么程度、为什么停下来。然后执行一次 Git 提交和 Tag。不需要立刻决定这个项目以后还会不会被重写先把状态从“模糊悬置”改成“明确归档”。做完这一步你会感受到整理仓库带来的连锁反应旧项目不再干扰你的注意力新的 Side Project 立项时你也会下意识去定义完成标准。如果你积累了一批未完成项目也可以把那套扫目录的 Python 脚本跑起来把最近的提交时间排序用十分钟的时间完成一次全量盘点。下一阶段可选的扩展方向有很多给所有归档仓库补上开源许可证把有复盘价值的项目写成博客文章把项目清单同步到 GitHub 的 issue 里做成公开 roadmap或者把你判断“为什么暂停”的过程做成一份个人决策日志。真正值得保留的未必是每一行代码而是代码背后的判断。
返回列表