先问一个基础问题:你知道GitHub上那些仓库里常见的LICENSE文件,到底在保护什么、约束什么吗?
我见过太多开发者,新建仓库时顺手选了MIT,理由是“大家都这么选”;也见过一些团队在README里写一句“本项目开源,欢迎使用”,结果整个仓库连一份协议文件都没有。表面上看好像没什么区别,等代码被别人抄走、被商业化公司包装成收费产品、或者发现别人在自己开源代码上只改了个名字就去融资时,才意识到事情没那么简单。
这篇内容适合所有在GitHub上放代码的人——不管你是个人开发者、创业团队,还是在公司内部维护公共组件的工程师。我会把开源协议的核心原理、最常见的那几份协议、怎么选、怎么加、怎么避坑,一次讲透。看完你会明白,为什么说开源协议不是“律师才需要懂的东西”,而是每个写代码的人都该有的基本素养。
1. 为什么说“没有开源协议,代码再好也别乱用”
很多人以为“开源”就是“把代码公开了,大家随便用”。这是最大的误解。真正的开源,指的是一种基于版权法的授权方式:代码作者保留著作权,同时通过开源协议明确告诉别人——你可以做什么、不可以做什么。如果没有协议,代码虽然公开可见,但它在法律上依然默认保留所有权利。
1.1 开源不代表放弃版权
我们在GitHub上看到的代码,本身是受著作权法保护的作品。作者把代码传到公开仓库,只是让对方“能看见”,并不等于允许对方“复制、修改、再发布”。这就像你在路边展览一幅画,观众可以欣赏,但不能把它拿回家,更不能直接拿去做商品包装。
所以严格来说,一个仓库如果没有LICENSE文件,任何第三方都不享有合法的使用、复制、修改和分发权利。这也是很多大公司拿到一个无协议仓库时不敢直接用的原因。哪怕作者在README里写了“欢迎使用”,这句话在法律上也不能替代一份完整的授权协议。
1.2 协议的两个核心作用:授权与约束
开源协议干的事,其实就是两件:一是授权,告诉你“你可以怎么用”;二是约束,告诉你“你必须保留什么、不能干什么”。
以最常见的MIT协议为例,它授权你用、改、卖、分发,几乎没有限制;但它有一个约束:必须在副本中保留原始版权声明和许可声明。再比如GPL协议,约束更重:你如果分发基于它的修改版本,整个衍生作品也必须使用GPL协议继续开源。
也就是说,协议的本质是“我给你使用权,但你必须遵守我定的条件”。不同的协议,约束力度不同,适用场景不同。这就像房东出租房子,M房东只要求你交房租,别把房子炸了就行;G房东会要求你入住后房间里必须种一棵树,而且将来转租时也必须让租客继续种树。这不是哪个更好,而是哪个更适合你的项目定位。
2. 六种最常用的开源协议,逐个拆开看你选对没有
这一部分是全文重点。我会把GitHub上出现频率最高的几类协议拿出来,不抄法条,只讲人话,讲清楚每份协议的核心机制、典型应用场景,以及你选择它时真正需要承担的后果。
2.1 MIT:最宽松、最省心的“放养协议”
MIT协议可以算是开源协议里的“最小可用版本”。整份协议的核心要点就是:任何人都可以自由地使用、复制、修改、合并、发布、分发、再许可和销售软件副本,唯一的条件是必须在所有副本中保留原始版权声明和许可声明。
这意味着什么?意味着别人拿了你的代码,可以闭源,可以商用,可以整合进收费产品,可以改名二次发布,只要他还保留你的版权声明。对很多开发者来说,这是一个相当省心的选择:代码放出去,想怎么被用都行,署名还在就行。
MIT协议为什么这么受欢迎?因为它几乎没有沟通成本。它的免责声明也同样直接:代码按“现状”提供,作者不对任何损害承担责任。你不需要担心误用、滥用带来的连带责任,因为协议已经把“不担保”写得很清楚。
适用场景很明确:你想让代码被最大范围地采用,想推动社区生态建设,或者做的是工具类、库类的基础组件——用MIT基本不会错。React、jQuery、Node.js生态里大量组件用的都是MIT。
2.2 Apache 2.0:比MIT多了一层专利盾牌
Apache License 2.0在宽松程度上和MIT很接近,但结构更严谨,条款更多。它除了版权授权之外,还包含一个非常关键的部分——专利申请。
简单解释一下:如果一份代码只写明“版权许可”,那使用者在实际操作中仍可能撞上代码里隐含的专利问题。比如作者为某个算法申请了专利,代码里用了这个算法,那使用者就算拿到了源码,也有可能被专利起诉。Apache 2.0明确授予了每位贡献者一定的专利许可权,等于帮使用者排除了一层隐形风险。
同时,Apache 2.0也设计了专利报复条款:如果某个使用者基于这份软件发起专利诉讼,那他在Apache 2.0下获得的所有权利会立即终止。这个机制维护了整个开源生态的平衡——你想用我的专利授权,就不能反手拿专利来告生态里的人。
另外,Apache 2.0会要求修改过的文件在显著位置标注变更内容,还要保留NOTICE文件里的信息。这听起来繁琐,但对大公司来说反而是好事,因为责任边界更清楚。很多云厂商和基础软件项目都偏爱Apache 2.0,比如Kubernetes、TensorFlow、Hadoop。
2.3 BSD:三个版本,差别就在一句话
BSD协议族也是老牌的宽松协议。BSD 2-Clause和MIT几乎等价,简单来说就是“保留版权声明即可,其他随便用”。
但BSD 3-Clause多了一条:未经事先书面许可,不得使用项目贡献者的名字或机构名来为衍生产品进行背书或推广。翻译一下:你可以很自由地用代码,但不能打着原作者旗号说“这是他官方推荐的”。这条约束对开源项目、对个人品牌保护都有意义,因此很多大学和研究机构喜欢用这个版本。
至于BSD 4-Clause,里面有一条“广告条款”——要求所有广告材料必须标明本项目由某机构支持,这和现代开源生态的兼容性很差,已经被广泛弃用。你看到还在用4-Clause的老项目,基本可以当遗产级代码看待。
2.4 GPL:最会“传染”的协议,也是争议最多的协议
GPL是自由软件基金会推出的强Copyleft协议。什么是Copyleft?你可以理解为逆版权。它的核心不是“放弃权利”,而是用著作权来保证软件永远对社会开放:任何人修改了GPL代码,只要他对外分发修改后的版本,那整个衍生作品也必须以GPL协议开源。
最典型的情况:你用了一段GPL代码,把它整合进自己的项目并发布给客户、上传到应用商店,那你的整个项目代码都必须在GPL协议下开放。正因为这种强传染性,GPL在开源社区里一直充满争议,有人觉得它代表了开源精神,有人觉得它在商业场景里太“咄咄逼人”。
还有一点需要说清楚:GPL管的是“分发”和“传导”,不是“使用”。你在公司内部用一段GPL代码来开发内部系统,不对外分发,这时候一般不会触发开源义务。真正的风险发生在交付阶段——不管是把安装包交付给客户,还是公开发布到网上,传播行为一旦发生,义务就跟着来了。
另外,GPL代码可以商用吗?答案是:可以,但不同的商业模式面临的约束完全不同。GPL并没有禁止商业化,而是强制要求商业化过程中也必须把源代码继续开放。所以不少纯订阅制SaaS模式的团队会刻意避开GPL,因为SaaS并不分发软件副本,传统GPL管不到它——但这一点同时催生了后面要说的AGPL。
GPL本身还有v2与v3的区分。v3在v2基础上增加了应对硬件锁定(TiVo化)、专利保护等条款,也让协议文本变得厚重;两个版本之间不是简单升级关系,混用时必须确认清楚项目声明的是“GPL v2 only”还是“v2 or later”。
2.5 LGPL与MPL:针对库和文件级别的温和解决方案
LGPL是给类库设计的弱Copyleft协议。它的核心思想是:你可以把LGPL的库链接进自己的项目里,你的项目本身可以选择闭源、商用;但如果你直接修改了LGPL库的源代码,那修改后的库文件必须继续开源。
听起来很友好,但这里有个容易踩的坑:动态链接和静态链接待遇不同。动态链接模式下,库是一个独立文件,你的程序只是调用它,LGPL义务不会传导到你的程序代码;静态链接时,你的代码和库被编译打包成同一个可执行文件,这种情况下LGPL通常会要求你提供足够的信息和对象文件,好让使用方有机会重新链接。很多人在这一步栽过跟头,后面我会在问题清单里细说。
MPL 2.0用的是文件级Copyleft。意思是:你改动了一个MPL协议的源文件,那么这个文件必须以MPL继续开源;但项目里其他文件用什么协议,不受影响。这让MPL在需要混合商业模块和开源模块时特别灵活。Mozilla有很长一段时间用它来管理Firefox的代码,Netscape早年选型也是这个路数。
2.6 还有几个不得不提的:AGPL、CC与Unlicense
AGPL可以理解成“面向网络服务的GPL”。传统GPL管不到SaaS场景,因为你只是运行服务,并没有分发软件副本;AGPL补上了这个洞:只要用户通过网络访问软件功能,使用方就被视为“接收了软件”,如果你修改了AGPL代码并提供给别人通过网络使用,就必须把修改后的源码开放出来。很多做后端服务和基础设施的公司对AGPL非常警惕,比如MongoDB曾经用AGPL后,不少云厂商就改用各自的商业授权来规避义务。
CC协议(知识共享协议)严格来说是为文档、图片、音频等作品设计的,不太适合直接用在代码上。但很多项目会在README、文档、博客资源上使用CC BY 4.0或CC BY-SA 4.0。要注意,CC BY-SA是Copyleft但面向内容作品,用它来授权代码时会带来很多语义冲突,社区里也普遍不推荐。
Unlicense、WTFPL这类“公域化”协议做得更彻底,相当于作者直接声明放弃版权。它看起来最自由,但因为没有足够明确的条款支撑,反而在严谨的商业场景里不受欢迎——律师们更希望看到一份语句清晰、案例充分的协议,而不是一句“爱怎么用怎么用”。
3. 一张表搞定协议对比,再用场景推导该怎么选
协议细节容易记混,我建议你把它当一张地图来用。先看每一份协议在“商用、修改、闭源、专利、署名”这些维度上的差异,再按自己项目的定位做取舍。
3.1 六大协议关键维度对比
我把最常见的维度整理成一张表,建议收藏。
| 协议 | 可否商用 | 能否闭源衍生 | 修改后是否强制开源衍生部分 | 是否授予专利许可 | 必须保留版权声明 |
|---|---|---|---|---|---|
| MIT | 可以 | 可以 | 否 | 未显式说明 | 是 |
| Apache 2.0 | 可以 | 可以 | 否 | 显式授予 | 是 |
| BSD-3 | 可以 | 可以 | 否 | 未显式说明 | 是 |
| GPLv3 | 可以 | 不可以 | 是,传染到整个衍生作品 | 有相关条款 | 是 |
| LGPLv3 | 可以 | 可以(链接库时) | 仅修改库本身时传染 | 有相关条款 | 是 |
| MPL 2.0 | 可以 | 可以(同项目其他文件) | 仅修改该文件时传染 | 有相关条款 | 是 |
注意,表格里的“专利许可”是简化说法。MIT和BSD没有明确的专利授权机制,不代表作者一定拿专利起诉你,只是协议本身没有把这件事说死;Apache 2.0则把专利授权写进了正式条款,价值就在这里。
3.2 从项目定位反向推断协议选择
选择协议不是看哪个“最火”,而是看你希望代码被如何使用。我会在选型前先问自己几个问题。
如果我希望代码被尽可能多的项目引用,推动生态扩散,那宽松协议是首选。个人小项目、通用工具类组件、前端组件库、演示代码,无脑选MIT完全没问题。几乎零沟通成本,别人用起来也放心。
如果我所在的公司对专利风险敏感,或者项目底层涉及大量设备、算法、协议栈,那我更推荐Apache 2.0。它把专利许可显式化,对下游使用方更友好,外企和法律合规团队的接受度也更高。
如果我想做一个底层库,允许别人直接调用,但又不想让其他人修改库本身后闭源,那我会考虑LGPL或MPL。MPL在很多需要“一个仓库里既有源码开放文件又有商业闭源模块”的场景里尤其好用。
如果我希望项目永远保持开源,任何外部分发都必须把改动回馈到社区,那就选择GPL。很多大型应用级开源项目这么选,因为它们更看重生态的可持续,而不是被闭源商用后“摘桃子”。
还有一种特殊场景:项目本身是SaaS服务,代码需要运行在服务器上给用户提供服务。如果你对“别人拿你的代码做同类服务却不回馈”非常在意,AGPL是一个硬选项,但一定要意识到它的强约束会让不少商业合作方望而却步。
3.3 协议兼容性:混用代码前一定要查这个
开源协议之间也讲“兼容性”。所谓兼容,指的是A协议的代码能不能合入B协议的项目,合并后的整体使用什么协议分发。
几个常用结论直接说:MIT和Apache 2.0的代码可以合入GPL项目,因为它们比GPL更宽松,GPL项目能继续以GPL协议整体分发;反过来,GPL代码不能合入MIT项目,因为GPL的传染条件不允许下游把它改成更宽松的协议。Apache 2.0官方声明与GPLv3兼容,但与GPLv2存在专利条款上的不兼容,这一点细节最容易被忽略。
MPL 2.0设计上考虑了兼容性,它允许在一定条件下与GPL合并分发,同目录下的其他文件可以保持其他许可证。这意味着如果你的项目是多文件、多模块混合,MPL提供了一条比LGPL更灵活的路。
还有一个容易被忽略的机制:向GPL项目提交PR时,你的贡献默认会被放进GPL协议里。除非项目方有额外的贡献者许可协议,否则你的代码一旦被合并,就自动“染上”GPL的色彩。这是很多开发者在给大项目贡献代码时没注意到的点。
4. 实战:在GitHub上给项目正确加上开源协议
选好了协议,下一步就是把这个选择落进仓库。这一节讲实际操作,从你新建仓库的那一刻说起。
4.1 仓库初始化和补建LICENSE两种路径
如果你刚创建新仓库,GitHub官方UI里有一个很显眼的入口:在创建仓库页面选择“Add a license”时,可以直接从协议列表里选一份模板。选好后GitHub会为仓库生成一个LICENSE文件,提交后即生效。
如果仓库已经运行一段时间,没有LICENSE文件,也很简单。在仓库首页点击“Add file”下的“Create new file”,文件名固定写成LICENSE或LICENSE.md,GitHub在文件名输入框下面会推荐协议模板,但要注意:直接在网页端生成模板前,建议先去choosealicense.com把协议文本仔细读一遍,确保和你预想的一致。
还有一种做法:在GitHub的“Settings”里通过页面进入License相关设置?严格来说,GitHub并没有一个“补协议”的独立设置入口,核心动作就是新建一个LICENSE文件并提交。提交信息建议写得清晰明确,比如“Add MIT license”,方便团队成员一眼明白是哪个节点引入的。
4.2 协议模板中必须改对的三处信息
从模板生成的协议文件,并不是复制粘贴就能收工。有几处信息不填对,协议可能在实践里变成“无效授权”。
第一处是版权声明。以MIT为例,你必须在模板里看到“Copyright (c) 2024 Your Name”这样的占位内容,然后把年份替换成首次发表年份,把名字替换成版权所有者。个人项目写自己的全名或常用ID,公司项目一般写公司法律实体名称,比如“Copyright (c) 2024 Beijing Example Technology Co., Ltd.”。注意,如果项目从2022年开始维护,每年都有人提交贡献,版权行可以写“2022 - 2024”,但核心原则是:首次发布的年份是关键。
第二处是协议名称和版本的对应关系。GPL这样的长协议,模板里可能带有升级说明。如果你的意图是“GPLv3 only”,那不要保留“or later”的措辞;如果你希望未来可以自动升级到GPLv4,那就要保留“or later”。这直接决定了项目后续协议变更的灵活性,很多人一开始没注意,后来想改都为难。
第三处是附加说明。Apache 2.0项目如果包含NOTICE文件,一定要补全其中对历史贡献者、第三方组件的记录。删除或忽略NOTICE文件,相当于切断了对上游的归属链路,这一点在商业合规审查时非常扎眼。
4.3 涉及他人代码时的署名与声明
绝大多数项目不是纯原创,一定多少引用了第三方库、代码片段或者魔改过别人的实现。这时候,光有自己的LICENSE还不够,还要处理第三方代码的归属问题。
如果引入了MIT、Apache 2.0等宽松协议的第三方库,通常做法是把它们的版权声明保留在一个专门的NOTICE或THIRD_PARTY_NOTICES目录下,或者在源码中保留对应文件头部的版权注释。如果引入的是GPL/LGPL/MPL代码,你还需要确保自己的分发方式满足对应协议要求,比如清楚区分哪些文件是第三方文件、哪些是自研文件,并声明它们各自的许可证。
还有一个容易忽略的细节:从Stack Overflow、博客、论坛复制代码时,如果作者明确附带了协议,你要遵循该协议;如果没有任何协议,需要先看页面条款是否允许复制,最稳妥的做法是给作者留言确认并保留来源记录。这不是矫情,而是你自己项目将来做开源审查时,唯一能拿得出手的合规凭证。
5. 常见问题与避坑实录
每次给开源项目做协议整理,我都会碰到一批几乎相同的问题。这一节做一份速查表,再分享几个我亲身经历过的案例教训。
5.1 先看这份高频问题速查表
| 问题 | 简短答案 |
|---|---|
| 没有加入LICENSE文件的项目,代码能用吗? | 严格来说不能用,默认保留版权,必须获得作者明确授权。 |
| GPL项目可以商用吗? | 可以,但对外分发时必须提供源代码,且衍生作品也需要GPL开源。 |
| MIT项目能被别人改成收费软件吗? | 可以,前提是保留原始版权声明和许可声明。 |
| fork了一个MIT项目,我能换成Apache 2.0发布吗? | 可以,但要保留原MIT版权声明,且你修改的部分可以采用Apache 2.0。 |
| fork了一个GPL项目,我能换成MIT发布吗? | 不行,GPL的传染性限制了你对原代码的重新授权。 |
| 我在GPL项目基础上做了一个内部工具,不对外发布,需要开源吗? | 通常不需要,GPL的义务主要在分发与传导环节被触发。 |
| 动态链接LGPL库,我的程序需要开源吗? | 一般不需要,但静态链接时要仔细确认,可能有提供重链接信息的义务。 |
| CC BY-SA协议能用在代码上吗? | 官方不建议,CC协议主要面向内容作品,用在代码上容易产生权利冲突。 |
| 我给GPL项目提了PR并被合并,我的代码算哪种协议? | 默认为GPL,除非项目有特别约定。 |
| 我不想做任何限制,只想代码公共化,用什么? | Unlicense或WTFPL,但要意识到这种放弃权利的方式在商业场景中认可度有限。 |
这些答案只是缩小到“普遍理解”层面,真遇到诉讼级别的问题,一定要找专业律师结合具体法域来判断。
5.2 我踩过的几个真实教训
教训一:给公司项目随手选了GPL,结果坑了全部门。有一年我参与一个内部通用SDK的选型,负责人看GPL“足够开放”,就把它定为SDK的协议。结果其他业务部门想闭源集成这个SDK,一看到GPL就炸了,合规和法务都不同意,最后不得不花大力气重写一遍和原项目有关的代码边界。那一次之后,我在给公司项目选协议时多了一个习惯:先问一句“这个项目要不要给商业闭源客户用”。
教训二:用一个看似MIT的包,结果它夹带了4-Clause BSD的旧代码。某个npm依赖的README写的是“MIT licensed”,但把源码翻到深处,发现有一份代码文件头部是Sun Microsystems年代的4-Clause BSD声明,里面有广告条款。虽然实际维权风险很低,但在合规审查时就非常麻烦。所以我现在看第三方依赖,不只信README上的协议标签,还会抽查几个文件头,确认没有历史协议残留。
教训三:贡献代码时没注意协议兼容性,被维护者拒收。我早期给一个小众开源项目提PR,项目本身是MPL 2.0,我直接把自己以前的一段MIT代码塞了进去。维护者提醒我,MPL和MIT组合本身可接受,但要明确标注第三方的MIT版权声明,否则后续维护者分不清代码归属。改完注释重新提交后,才被合并。从那次开始,我写代码前都会留意当前仓库的协议偏好,然后尽量让自己的提交内容保持干净的原创性,避免夹带不明来源的代码片段。
教训四:协议不是设定一次就完事,它需要被持续维护。项目火起来之后,外部贡献者会增多,这时候如果你没有CONTRIBUTING文件,没有明确说明“为本仓库提交代码视为同意在本仓库许可证下分发”,那后续协议变更是非常棘手的事。因为每个贡献者原则上都对自己的代码拥有著作权,未经他们同意,你没法把整个项目从MIT换成GPL。我现在做新仓库的第一天就把CONTRIBUTING文件建起来,写明贡献协议,后面省掉很多麻烦。
最后再说一点个人体会。开源协议这东西,界面上一看就是一屏英文,平时开发时也根本不会多瞅一眼;但一旦项目进入商业合作、公司合规或者融资尽调阶段,它就变成了实实在在的法律凭据。我现在的习惯是:接手任何第三方包之前,先看包里有没有LICENSE,再看是什么协议;自己新建项目时,把协议当成和代码一样重要的事情来对待,甚至比代码更早定下来。希望这篇拆解能帮你少走一点弯路。