Git和Subversion是什么?

13

我看到很多网站提到git、github、svn、subversion等,但我从来不知道这些东西是什么。我也经常听到像'svn repo'、'commit'和'push'这样的术语 - 我尝试谷歌搜索,但好像我的知识太少了,我甚至不知道该从哪里开始。

有人能给我一个最初的推动,这样我就可以继续自己的研究了吗? 这些东西都是关于什么的?

谢谢!

伙计们:非常感谢你们提供的所有非常详细和全面的解释。我希望我能选择更多的答案,但不幸的是SO不允许那样做(他们应该有一个投票第一、第二和第三名的功能或类似的)。非常感谢你们所有人!


3
哇,这让我想起小时候上班的第一天,其他开发人员问我:“你知道配置管理是什么吗?” 显然我的回答(“不知道”)很有趣。 SCM 是软件开发实践的基石。 - Jonathan Julian
请参阅http://stackoverflow.com/questions/1438662/which-of-the-two-is-bettergit-or-svn/1438697#1438697,因为Git和Subversion实际上彼此非常不同。 - VonC
7个回答

23

版本控制(又称修订控制)。

考虑以下问题。你正在与他人合作的项目中共享文件。你们俩都需要编辑一个名为“WhateverController.java”的大文件。

最原始的处理方式是不同时编辑该文件,但这时你们俩必须保持一致。当你有一个团队时,尤其是如果团队有数十、数百或数千名成员(在开源项目中很常见),那么这就完全不可能了。

早期,解决这个问题的原始“方法”是使用签出/签入机制。当你需要编辑文件时,“签出”文件,文件被锁定,直到你“签入”它后才能进行编辑。这是通过适当的软件实现的,例如微软耐人寻味的垃圾软件SourceSafe。但是如果有人忘记了“签入”文件,则在使用该文件时其他人无法编辑该文件。然后有人去度假或以其他原因离开项目,结果就是无休止的混乱、困惑,通常还会丢失大量的代码。这增加了巨大的管理工作。

接着出现了CVS,随后是Subversion,作者称其为“正确的CVS”,因此CVS和Subversion本质上是相同的想法。对于这些工具,实际上没有签出操作。你只需编辑需要的文件并进行签入。请注意,实际文件存储在中央服务器上,每个用户还在自己的工作站上运行软件。这个位置在服务器上被称为仓库。

那么,如果两个人在CVS/Subversion上都在操作同一个文件呢?它们将会被合并,通常使用GNU diff和patch。'diff'是一个提取两个文件之间差异的实用程序。'patch'使用此类'diff'文件来修补其他文件。

如果你正在一个函数中修改 WhateverController.java 文件,而我也在同一文件的另一个函数中修改该文件,当你完成你的工作后,你只需将更改提交,这些更改会应用于服务器上的文件。同时,我本地的拷贝不知道你的更改,因此你的更改对我的代码没有任何影响。当我完成我的更改后,我也将文件检入。但是现在我们有了这个看似复杂的情况。
让我们把原始的 WhateverController.java 文件称为文件 A。 你编辑该文件,得到的结果是文件 B。 我在不同的位置编辑了相同的文件,没有使用你的更改,这个文件是文件 C。
现在我们似乎有了一个问题。文件 B 和 C 的更改都是针对文件 A 的更改。所以在像 SourceSafe 或 Dreamweaver 这样的荒唐程序中,通常会覆盖文件 B 的更改(因为它先被检入)。
CVS/Subversion 和可能 Git(我对 Git 几乎一无所知)生成补丁而不是仅覆盖文件。
文件 A 和 C 之间的差异会产生并形成补丁 X。文件 A 和 B 之间的差异会产生并形成补丁 Y。
然后将补丁 X 和 Y 应用于文件 A,这样最终的结果就是文件 A 加上我们各自工作站上对 B 和 C 进行的更改。
通常这样做是完美无缺的。有时我们可能会在同一段代码中工作,此时 CVS/Subversion 将通知程序员出现了问题,并在文件中呈现出该问题。这些问题通常很容易解决,至少我从来没有遇到过什么麻烦。图形化工具例如 Visual Studio、Project Builder(Mac OS X)等通常会显示两个文件和冲突,这样你就可以选择保留哪些行和丢弃哪些行,如果需要手动合并冲突,也可以手动编辑文件。
因此,源代码控制本质上是解决多人同时对同一文件进行修改的问题的解决方案。基本上就是这样。
希望这能解释清楚。

编辑:像Subversion和可能的Git这样的良好源代码控制系统还有许多其他好处。 如果出现问题,您可以回到其他版本,因此您不必手动备份所有内容。 实际上,至少使用Subversion,如果我搞砸了什么或者想查看旧版本的代码,我可以这样做而不会干扰任何其他人的工作。


这绝对是我听过的关于版本控制最清晰、最直接的解释! - Yuval Karmi
作为一个独立开发者,我是否可以在本地使用Subversion或Git来处理我的应用程序?这对于跟踪自己软件中的更改可能会有所帮助。 - Yuval Karmi
3
是的,完全可以自己使用svn或git,并且非常有用。 - ebneter
3
通常情况下,合并是通过三方合并完成的,而不是应用补丁进行的。这意味着如果存在冲突(您编辑了同一文件的相同区域),则会在重叠区域显示您的版本和他们的版本之间的冲突标记(在某些版本控制系统中,您还可以选择显示公共/基础版本)。 - Jakub Narębski
3
使用git(或Mercurial、Bazaar)来管理自己的应用程序非常容易。使用CVS或Subversion略微复杂一些(但您的编辑器/IDE/图形化工具可以帮助自动化这个过程)。 - Jakub Narębski

9
GIT、Subversion等都是关于版本控制的技术。如果您在项目中使用这些技术,所有源文件都存储在所谓的仓库(也称为“repo”)中 - 除了不需要版本控制的文件(大文件、用户特定文件等)。
版本控制的一些优点包括:
  • 分支。 您可以为每个正在处理的错误创建一个新分支,而不会篡改其他开发人员的代码。大多数版本控制系统将进行廉价的复制,即新分支几乎不会占用额外空间。
  • 版本控制。 您始终可以返回旧版本,更新到新版本或查看提交日志以查看代码发生了什么。像TortoiseSVN这样的GUI工具甚至提供了图形化的差异实用程序。术语“commit”基本上意味着将文件的新版本放入存储库(或添加/删除文件)。版本控制系统还支持“合并”,即自动合并由多人更改的文件上的更改(通常基于行)。
  • 同时开发。 多个开发人员可以拥有自己的“工作副本”(也称为“checkout”)。这意味着 - 即使您不使用分支 - 您的本地代码副本也将编译,即使其他人当前正在项目上工作(因为他们有自己的工作副本)。当您认为当前的代码对其他人有用时,您可以提交更改,其他人可以更新其副本。
  • 中央存储和备份。 这适用于CVS / Subversion / ...,而不适用于GIT。这是一个优势,因为有一个中央位置可以提交更改,并从其他开发人员那里拉取更改。
  • 分布。 但这适用于GIT(不适用于Subversion)。这意味着可以为项目创建多个独立的存储库。例如,Linux内核就有这个功能。人们可以在其上工作的自己的存储库上“拉”下来 - 它就像一个完整的存储库,即本地进行提交而不是到服务器。如果您想包含其他人的存储库(或公共存储库,如kernel.org)的补丁,则只需将这些更改“拉”到本地存储库即可。如果您想向其他人提供您的补丁,则将更改“推送”到远程存储库(如果您拥有权利)。

希望这解释了你提到的术语。我认为开始使用版本控制的好方法是使用Subversion,如果可能的话使用TortoiseSVN for Windows。甚至有一本免费的书 - Version Control with Subversion


8

7
"The Git Parable"是由GitHub背后的人之一Tom Preston-Warner(mojombo)所写,描述了版本控制系统(如Git)可能是如何产生的...同时也阐述了为什么需要(分布式)版本控制系统。
另请参阅Better Explained的文章“版本控制的可视化指南”。
使用版本控制系统有许多优点。 让我们按照逐渐增加的复杂性顺序列出它们:增加开发人员、增加项目大小/项目历史记录大小、更复杂的工作流程等等。

单个开发者,单个分支

即使您是项目的单个(唯一)开发者,并且(至少在短期内)不打算更改它,版本控制系统仍然很有用。 它可以:
  • 回到可用的工作版本。如果你正在进行项目开发,却意识到你完全搞砸了,尝试的方法不起作用,你不知道如何让它工作,那么能够简单地返回到上一个可用的版本并重新开始是很好的。

    这意味着你应该在拥有可用版本时进行提交,即在完成单个功能、单个问题或单个功能或问题的一部分时进行快照(当然也有例外情况,请参考下面)。为了避免丢失太多工作内容,您应该经常提交,最好(请参考下面)在完成单个特性、单个问题或单个特性或问题的一部分时提交。

    您还需要了解您所做的事情以及最近在做什么。这意味着您应该描述每个变更集(每个提交)。

  • 注释文件/浏览历史记录。除非您具有完美的记忆力,否则有时您会想知道为什么(以及何时,在存在多个开发人员的情况下也可以知道谁)编写了给定的一组代码行。注释并不总是足够的。为此,您可以使用(如果您的版本控制系统提供)逐行文件历史注释(scm annotatescm blame)或其他类似的工具,如Git中的所谓“拾音器”搜索,其中您可以搜索/浏览引入或删除给定字符串的提交历史记录。

    为了使其有用,您需要编写良好的提交消息,描述更改和更改的目的,以便您知道为什么进行了更改。

  • 二分历史记录以查找错误。现代版本控制系统提供了一种查找错误的替代方法(与插入打印语句或调试器相比),至少在某些情况下是这样的。当您注意到一个漏洞或获得一个漏洞报告,并且该漏洞不是最后一次更改的结果时,您可以使用版本控制系统(csm bisect)自动查找引入漏洞的提交(第一个具有给定漏洞的提交)。版本控制系统使用项目历史记录上的二分法检索(检出)您标记为良好(没有漏洞)或坏的版本,直到找到引入漏洞的提交为止。

    为此,您应始终确保版本工作正常(或至少能够编译),否则您将无法确定提交是否具有漏洞。您应该保持提交的大小较小(更改不多),以便在找到引入错误的提交时,只需要检查受更改影响的少量行。您还需要良好的提交消息,以便您知道更改是为什么(并决定更改是否正确)。

多个分支

后来,您将需要版本控制系统的另一个特性:在项目的不同开发线路(风味)上并行工作的能力,称为分支。这包括但不限于:

  • 给发布打标签。当您将项目的新版本发布给更广泛的公众时,您需要标记(标记)已发布的版本。这样,当有人告诉您您的项目的X.Y版本存在错误时,您将能够检查此版本,并检查是否可以重现此错误(并可能通过二分法找到错误,如上所述)。即使您不发布您的项目,如果您在不同的地方部署了可能不同的版本,则可能会有用。

    因此,这些标记需要是不可变的(当然)。

  • 长期分支。假设您发布了项目,有人发现了一个错误。您可能希望能够发布修复版本,而无需停止新功能的工作,并且无需从开发中发货可能不稳定并包含多个其他错误的版本。您还希望在您正在使用的版本中也具有bugfix(如果未独立修复)。

    为此,您将使用长期存在的分支:维护分支,其中您只提交bugfixes,以及开发分支(或主干),在其中进行新的工作,介绍新功能等。可能会有更稳定的各种分支。例如,Git项目具有四个这样的分支:“maint”用于bugfixes,“master”用于相当稳定的更改,“next”用于开发工作,“pu”或“建议更新”分支。在其他工作流中,您可以为每个版本单独维护(修复错误)分支。

    引用Joel Spolsky的话:“将稳定和dev代码分开正是源代码控制应该让您做的事情。”

  • 主题(功能)分支。当您要并行处理多个问题时,其中每个功能需要多个提交才能完成,您可能希望在单独的分支中开发每个功能(每个主题)。这样,您将能够从处理一个功能转换为处理另一个功能(其他主题)。

    如果您与多个开发人员合作,则此工作流程尤其重要,请参见下文。

多名开发人员

版本控制系统最重要的功能之一是,它使不同的开发人员之间能够协作,允许多人在同一项目上工作,而不会互相干扰彼此的更改。其他答案已经很好地描述了此功能,因此我不会详述。

有关版本控制系统使用各种方法允许合作的描述,请参见Eric S. Raymond(《大教堂与集市》和《Unix编程艺术》等著作的作者)的进行中的工作“理解版本控制”。


4
Git和Subversion(也称为svn)都是源代码控制或版本控制系统。它们帮助您管理源代码并跟踪系统管理的每个文件的更改历史记录。维基百科文章metismo链接可能会有所帮助。
Github是一个托管和管理git存储库的服务。它基本上将存储库放在网上,以便多个人可以与存储库进行交互。
提交命令通常将一组更改存储到源代码控制存储库中。这将在存储库中创建一个新的修订版本。
推送命令仅适用于分布式版本控制系统,如Git或Mercurial(也称为hg)。推送允许将更改从一个存储库移动到另一个存储库。分布式版本控制系统的概念是每个用户都有自己的存储库。当用户完成更改时,用户将它们推送到其他存储库(可能是中央项目存储库,或作为另一个用户存储库的补丁)。
这些系统的目的是:
- 存储开发过程的历史记录 - 提高多个开发人员之间的协作 - 允许恢复和修复旧版本的代码 - 将源代码更改与特定功能或错误相关联(请参见fogbugz和kiln) - 为实验或并行开发创建代码变体(分支)

2

源代码存储库。

基本上是一种共享代码的方式,团队成员可以看到谁在什么时间添加了哪些代码,谁在什么时间更改了什么内容等等。


2
请查看(免费在线)subversion书籍第一章。它描述了版本控制系统(如subversion)的相关内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接