git cherry-pick 和 revert 怎样使用三方合并

原作者:Julia Evans · 原文发布于 2023 年 11 月 10 日 · 中文翻译与技术校注:未完纪

原文:How git cherry-pick and revert use 3-way merge

你好!前些天我想向别人解释 git cherry-pick 是怎么工作的,结果把自己绕晕了。

问题出在这里:我以为 git cherry-pick 基本上就是应用一个补丁,可我真的照着这个思路去做时,却行不通!

这篇文章就来聊聊我原先以为 cherry-pick 在做什么(应用补丁),为什么这种理解不完全准确,以及它实际采用的做法——“三方合并”。

我们会钻进相当细的实现细节。想把 Git 用好,完全不必懂这些;不过,如果你和我一样,对 Git 内部的运作方式感到好奇,那就继续往下看。

cherry-pick 并不只是应用补丁

我过去对 git cherry-pick COMMIT_ID 的理解是:先计算 COMMIT_ID 的差异,例如用 git show COMMIT_ID --patch > out.patch;再把补丁应用到当前分支,例如执行 git apply out.patch。

先说清楚:这个理解在大部分时候都说得通,继续用它理解 cherry-pick 也没问题。只是某些细节并不是这样,而我觉得这些细节很有趣。

假如碰上合并冲突,我尝试“计算差异,再应用补丁”,会得到这样的结果:

$ git show 10e96e46 --patch > out.patch
$ git apply out.patch
error: patch failed: content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown:17
error: content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown: patch does not apply

它直接失败了,没有把我带入一个可以解决冲突的流程,也没有告诉我该怎样解决问题。

真正运行 cherry-pick 时,结果却不一样:它会进入合并冲突状态。

$ git cherry-pick 10e96e46
error: could not apply 10e96e46... wip
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".

这样看来,“Git 在应用一个补丁”的理解并不完全正确。可错误消息明明又说“could not apply 10e96e46”,它似乎也不能算错。到底发生了什么?

cherry-pick 究竟在做什么?

我去翻了 Git 的源码,想弄明白 cherry-pick 的工作方式,最后找到 sequencer.c 中的这行调用:

res = do_recursive_merge(r, base, next, base_label, next_label, &head, &msgbuf, opts);

所以,cherry-pick 其实是在……合并?怎么会这样?它在合并什么?而且,合并这件事本身到底是怎么做的?

我意识到,自己其实并不清楚 Git 的合并机制。搜索之后,我发现它会做一种叫“三方合并”的操作。那是什么呢?

Git 如何合并文件:三方合并

假设要合并下面两个文件,分别叫 v1.py 和 v2.py。

v1.py:

def greet():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name

v2.py:

def say_hello():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name

其中有两行不同:函数名是 greet 还是 say_hello,以及 name 的值是 "julia" 还是 "aanya"。该选哪一个?光看这两个版本,好像无从判断。

但如果我告诉你,原来的函数是这样的,也就是 base.py:

def say_hello():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name

事情一下就清楚了:v1 把函数名改成了 greet,v2 把 name 改成了 "aanya"。合并时,只要把这两项修改都保留下来:

def greet():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name

可以请 git merge-file 来合并。原文得到的结果与预期相同:保留 def greet() 和 name = "aanya"。

$ git merge-file v1.py base.py v2.py -p
def greet():
    greeting = "hello"
    name = "aanya"
    return greeting + " " + name⏎

这种同时使用两个文件版本以及它们的原始版本来合并的方法,就叫三方合并。作者还做了一个可以在浏览器里尝试的 三方合并小工具。它搭得很快,对手机不太友好。

以 base 为参照,v1 修改函数名、v2 修改姓名;合并结果同时保留两项修改。下方对比 cherry-pick Y 使用 B、X、Y,而 revert Y 使用 B、Y、X。
三方合并与两个命令的输入对应关系。未完纪原创示意图,依据本文示例绘制,并非 Git 界面截图。

Git 合并的是修改,而不只是文件

我这样理解三方合并:有一个原始文件,以及针对它的两组修改,Git 尝试以合理的方式把两组修改放到一起。有时它做不到,例如两边都改了同一行,这时就会产生合并冲突。

Git 也能尝试合并多于两组修改:可以有一个原始版本和八组修改,让 Git 试着协调它们。这叫 octopus merge(章鱼合并)。我没有做过,所以也了解得不多。

Git 怎样用三方合并来应用一个提交

现在来一点有意思的变化。原文把 rebase、revert、cherry-pick 中的“应用补丁”描述为:不是真的先生成补丁文件再应用,而是做一次三方合并。

把提交 X 的修改应用到当前提交时,和上面的三个输入可以这样对应:

  1. 当前提交中的文件版本是 v1。
  2. 提交 X 之前的文件版本是 base。
  3. 提交 X 中的文件版本是 v2。
  4. 用与 git merge-file v1 base v2 相同的基本思路把它们合并。严格来说,Git 内部不会直接运行这个命令,而是调用相应的 C 函数。

base 与 v2 放在一起,就能被视为那个“补丁”:两者的差异,正是希望施加到 v1 上的修改。

cherry-pick 的输入是什么

假设提交关系如下,要把 Y cherry-pick 到 main:

A - B (main)
 \
  \
   X - Y - Z

把它换成三方合并的语言:B 是 v1,X 是 base,Y 是 v2。因此,X 和 Y 共同描述了需要应用的“补丁”。

原文接着用一句话概括 rebase:像把 cherry-pick 重复做很多次。这个说法有助于建立直觉,不过具体行为仍要受上面的后端区别限制。

revert 的输入是什么

现在,假设在以下历史上运行 git revert Y:

X - Y - Z - A - B

B 仍然是 v1,但这次 Y 是 base,X 是 v2。它和 cherry-pick 的关系非常直接:把 X 和 Y 对调,因为我们要应用的是“反向补丁”。

revert 与 cherry-pick 在 Git 中联系紧密,连命令的实现入口都放在同一个 revert.c 文件里。

“三方补丁”这个办法很巧妙

通过三方合并,把某个提交当作补丁应用到另一处,真是个很巧妙的办法。我很惊讶,以前竟然没听说过!我不知道它有没有专门的名字,不过很想叫它“三方补丁”。

想法是:用两份完整文件来定义补丁,一份是修改前,另一份是修改后,也就是本文中的 base 与 v2。加上接收修改的当前文件,总共涉及三份文件。

与普通补丁相比,这样会给合并提供更完整的上下文,因为我们拥有修改前后的整份文件。

下面是原文用来表达差异的大致示意,不是可直接交给 Git 应用的规范补丁文件:

@@ -1,1 +1,1 @@:
- def greet():
+ def say_hello():
    greeting = "hello"

相应的“三方补丁”可以想象成下面这样。它不是任何真实的文件格式,只是作者为了说明概念而虚构的表示方法:

BEFORE: (the full file)
def greet():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name
AFTER: (the full file)
def say_hello():
    greeting = "hello"
    name = "julia"
    return greeting + " " + name

《Building Git》也解释了这件事

除了 Git 源码,我当时只在 James Coglan 的 《Building Git》 中找到对 cherry-pick 底层如何使用三方合并的解释。我原以为《Pro Git》也会讲,但就我找到的内容而言,好像没有。

我还准备去买《Building Git》,后来才发现自己早在 2019 年就买过,正好拿来参考。

真正的合并比这里复杂得多

Git 合并不只有三方合并这一层。原文提到作者当时还不了解的 recursive merge,也提到文件删除、移动等处理细节,以及不止一种合并算法。

作者认为《Building Git》可能是继续深入的好去处,不过也坦言自己还没读完整本书。

那么,git apply 做了什么?

我也查看了 git apply 的源码。果然,它在 apply.c 里。代码会解析补丁文件,然后在目标文件中寻找适合应用补丁的位置。核心逻辑大概在 这里:我的理解是,它先从补丁指定的行号开始,再向前后搜索,寻找匹配位置。

/*
 * There's probably some smart way to do this, but I'll leave
 * that to the smart and beautiful people. I'm simple and stupid.
 */
backwards = current;
backwards_lno = line;
forwards = current;
forwards_lno = line;
current_lno = line;
for (i = 0; ; i++) {
   ...

注释的大意是:“也许有更聪明的办法,但就留给聪明又优秀的人去做吧;我只是采用一个简单笨办法。”这段逻辑相当直观,也符合我最初的猜想。上面保留了原文的省略号,因此它是阅读用的源码片段,并不是完整可编译程序。

git apply –3way 怎样工作?

git apply 还有一个 --3way 选项,也能使用三方合并。因此,只看应用改动这一步,前面的思路其实可以写成:

$ git show 10e96e46 --patch > out.patch
$ git apply out.patch --3way
Applied patch to 'content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown' with conflicts.
U content/post/2023-07-28-why-is-dns-still-hard-to-learn-.markdown

不过,--3way 使用的不只有补丁文件中的文字。这个补丁开头还有:

index d63ade04..65778fc0 100644

d63ade04 与 65778fc0 是旧、新文件版本的对象标识。它们提供了把补丁和 Git 对象数据库联系起来的线索。原文据此解释:Git 可以取回文件版本来完成三方应用;如果别人通过邮件发来补丁,而本地缺少需要的 blob,就无法完成这一步。

原文列出的报错如下,但命令行漏写了 --3way:

$ git apply out.patch
error: repository lacks the necessary blob to perform 3-way merge.

三方合并比 Git 老得多

后来有读者指出,三方合并远早于 Git,可能可以追溯到 20 世纪 70 年代末。原文给出了一篇 2007 年讨论三方合并的论文,供有兴趣的人继续阅读。这里保留作者原有的年代不确定性,并不把它当作已经查明的发明年份。

就聊到这里

我原来竟然不了解 Git 内部应用改动的核心方式,这让我很意外;把它弄明白的过程也非常有趣。

我对 Git 的用户界面有不少意见,但这一点不在其中。三方合并用一套相当统一的思路解决了几类问题,而且直觉上容易理解。许多程序员本来就习惯“应用补丁”的想法,至于底层借助三方合并实现,完全可以只是平时不必操心的实现细节。

原文末尾还提到,作者当时正在制作一本关于 Git 的 zine 技术小册子,读者可以通过她的 公告邮件列表获取发布消息。这里是对 2023 年写作背景的保留,并非仍未出版的实时状态。

版权与授权:原文作者为 Julia Evans。本次核验的文章页与 About 页未显示可直接适用于全文的开放许可证,故不擅自标为 Creative Commons。所引用 Git 源码的版权与许可证仍归其项目及贡献者,参见 Git COPYING。正文校注与示意图为本次编辑新增,未执行文中命令。

版权与许可全文

以下保留本页涉及的来源材料或示例代码的版权、许可条件与免责声明;各自适用范围依原声明。中文翻译及编辑标注:未完纪,2026-10-05。

GPL-2

                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Moe Ghoul>, 1 April 1989
  Moe Ghoul, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容