65.9K
CodeProject 正在变化。 阅读更多。
Home

选择版本控制系统 - 新手选项指南

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (35投票s)

2012年8月12日

CPOL

45分钟阅读

viewsIcon

103781

一份关于版本控制系统替代选项的新手指南

引言

您需要版本控制吗?

  1. 我从未用过版本控制
  2. 我认为我可能想尝试版本控制
  3. 我希望版本控制能为我服务
  4. 我不想为它服务

如果这描述了您,那么请继续阅读,希望这能帮助您为自己选择一个版本控制系统。虽然我不能保证它会让您的生活变得更好,但如果您找到一个真正“为您服务”的系统,那么它至少不会让您的生活变得更糟,我敢打赌,您会发现一些您甚至没想到的好处!

作为一名初学者,我猜想在您开始(或者在我重新开始)使用版本控制很久之后,您甚至都不会想到它。但在某个时候,它很可能会进入您的视野——那种突然意识到,如果能追踪代码中的各种更改,您的生活会更轻松。希望它不是灾难的结果(对我来说几乎发生了,幸运的是我及时发现了),并且我后来发现了很多使用版本控制的其他好理由。

因此,我花了一些时间研究了几种版本控制系统(VCS),试图从中挑选一个,并想分享我的经验,因为对于初学者来说,仅仅选择一个然后就直接开始使用可能是一个相当令人生畏的想法——毕竟,您已经在陡峭的学习曲线上,为什么还要同时学习一个VCS来增加一倍的头疼呢?尽管这通常是您会得到的建议类型

使用这个 [插入您能想到的几乎所有系统的名称],学习命令行,它很棒

这不是我喜欢的乐趣。**我想要轻松**。

如果您只想直接跳转到比较,请随意。

如果您对我的看法感兴趣,了解所有术语的含义,那么我已经尽力加上了我的一点见解,希望能为已有的数百万解释增添色彩。为什么?其中大多数是由专家撰写的,虽然第一句话是为“菜鸟”模式写的,但紧随其后的是几句“爱因斯坦”模式的话。我不可能进入爱因斯坦模式,我才刚刚开始。所以希望我的版本对于那些拥有几周前我所拥有的知识水平的人来说更有用。

目录

背景

一些基本假设

  1. 您希望使用分布式版本控制系统,而不是历史上更受青睐的工具,如Subversion
  2. 您想要一个GUI,并且不想学习命令行。

为什么要做出这些假设?反过来说,如果您是命令行大师,那么您可能不需要我来帮您选择VCS。分布式VCS风靡一时,几乎所有东西似乎都在朝着这个方向发展,所以如果您曾经想参与一个开源项目或将您的项目作为开源提供给世界,那么现在它可能是一个更好的选择。

概念

如果您了解基础知识或只想直接跳到比较部分,您可以直接这样做

首先,关于版本控制的一些基本概念,我通过尝试、犯错、找出错误并从中学习来掌握它们。如果通过阅读学习对您有用,那么这可能会让您对选择VCS的部分有更深的理解;否则,选择一个并开始犯错吧,很难把事情完全搞砸。我试图按逻辑顺序排列它们,但有时可能会有点循环。

这是我的理解,从初学者到初学者。如果它根本上是错误的,请告诉我;如果它看起来有点过于简化,那对于目标读者来说可能是可以接受的。我猜想我在几个月/几年后回顾时会对自己微不足道的知识水平感到惊讶,希望我不会回顾时感到困惑!

请记住,我在这里专注于*分布式*版本控制,这些术语在像Subversion这样的历史VCS中可能意味着不同的东西。

说到这里,我认为所有不同的VCS和DVCS有时可能会使用不同的术语来表示完全相同的事情,或者至少是非常相似的事情;您也可能会发现同一个术语被用于两个不同的事情——哦,太好了,这让事情变得更容易了!

存储库

构成您项目的文件集合(有或没有版本控制)**加上**由您的VCS维护的数据库。VCS只是让您能够轻松地跟踪更改、创建新版本、创建分支等,并轻松地在它们之间切换。

存储库可以是本地的,位于您的硬盘上,也可以是远程的,位于某个服务器上。在分布式VCS的世界中,即使处理一个远程托管的项目,您的本地副本也是远程副本的完整副本,也就是说,它是一个完整的存储库,而不仅仅是您碰巧在处理的那一部分。

分布式

如果您是独自工作,尤其是如果您将只在本地工作,那么完全不必担心这一点。.

由于我没有使用过远程存储库,我可能需要被纠正。

分布式VCS系统的关键在于,*不必*有一个主存储库,每个贡献者都拥有整个存储库的完整副本。因此,您是点对点工作,而不是客户端-服务器工作。一个中央存储库可以充当主存储库,但同样,它也可以只是一个有用的存放点,所有开发人员都将更新发送到那里,并从那里获取其他人的更新。开发团队在定义其代码的主版本方面如何行为,完全取决于他们。

因此,不必有一个守门员在接受每个人的更改之前对这些更改进行审查,然后将它们合并到中央代码库中。通常会有人执行这个角色,但由于每个开发人员都拥有存储库的完整副本,因此VCS可以正常工作,这只需要是为了保持理智。

每个开发人员都拥有存储库的完整副本,这带来了各种各样的好处,但本文不讨论这个问题,所以如果您需要知道(或只是想知道),那么可以通过Google轻松找到很多评论。

工作目录

没有版本控制,您的工作目录就是您的项目文件夹(及其所有子文件夹)。有了分布式版本控制,情况也是如此,只是您能够非常快速、非常轻松地将工作目录更新到您想要处理的任何代码版本。

分支和尖端

分支本质上是将您的代码的一个版本复制成两份。然后您可以独立地更改这两个副本,一个副本的更改不会影响另一个。

Branch and Tip

两个分支,主干和例如功能分支

在上图中,蓝色矩形代表您项目的特定版本,即特定时刻的快照。而箭头代表您对代码进行的更改,添加和删除文件等。从A1到B1的深橙色箭头代表了分支的创建以及代码更改。

所以分支在概念上听起来非常简单,它们确实如此,但随后就会变得复杂,有无数不同的方式,特定个人和不同项目决定如何处理他们在项目中想要进行的各种更改(新功能、错误修复等)。在单个VCS中也有不同的分支方式,当您查看多个VCS时,还有更多种方式。

为了保持简单,我将定义一个简单的操作模型,其中有一个中央或主分支,我们称之为*主干*(您也会听到基线或默认等术语)。我们很少直接修改主干。大部分情况下,我们会创建一个分支,在上面进行更改,然后在完成后将其合并回主干。

尖端(Tip)只是一个分支线的末端,在它被合并到主干或其他分支之前。

变更集

代表提交和前一次提交之间差异的所有更改(您的项目的两个版本)。假设您修改了项目中的一个文件,然后提交了这个更改,那么变更集就是您刚刚进行的提交与前一次提交之间的差异,也就是说,您对那个文件所做的更改。

如果您回顾一下上面的图片,A1和A2之间的更改就是您进行的提交所产生的变更集,该提交创建了A2。

因此,当您进行一次提交时,您基本上定义了一个起点(前一次提交)、一组更改和一个终点(新的提交)。

主干

这是另一个我可能需要被纠正的地方。

作为一个术语,我认为它有点像是从分布式之前的日子沿袭下来的,当时(我认为)总是有个主干,它在中央存储库中充当主分支(一个统治所有分支的分支)。在分布式世界中,它并没有消失,但也不是必需的,您可以拥有花哨而复杂的代码分支模型。然而,据我所知,大多数人似乎已经在他们选择的操作模型中整合了一个(概念上的)主干替代品。我的模型是我前面描述的操作模型,我有一个名为主干的分支,我从不直接对其进行更改,只通过合并分支到其中,但我不必如此工作。

如果您仔细想想,那么如果没有某种流程将项目中可能由不同的人(甚至只是您自己)进行的各种更改汇集在一起,那么就会导致混乱。我认为像Subversion这样的历史VCS通过层级来实现这种控制,主干是层级的顶端。在分布式世界中,人们和项目决定如何去做,而不是由VCS告诉他们怎么做,也就是说,他们定义了一个操作模型,这个模型中必须包含一些在概念上类似于主干的东西。

合并

使分支形成循环,或将它们连接回主干,或将它们与其他分支连接。总之,这是不同分支连接起来的过程。本质上,它是分支的逆过程。所以,如果分支创建了一个代码版本的两个独立副本,那么合并就是将两个独立版本合并成一个新的、包含两者的单个版本。假设您从分支 A 的版本 1(包含单个文件 *index.php*)开始。然后您创建了一个新的分支 B,并在分支 B 中添加了第二个文件(*menu.php*),并在分支 A 中添加了不同的文件(*footer.php*)。现在这两个分支非常不同。如果您现在合并这两个分支,您将创建一个包含所有三个文件的新版本。

如果您喜欢图片,请尝试跟随下面的图片。如果您更喜欢文字,我上面也添加了图片的文字描述。与之前一样,蓝色矩形代表快照,箭头代表您进行的更改。其中一种更改类型不是实际的编码,而是两个快照的合并以创建新的快照,即合并 B2 和 C2 以创建 B3。同样,合并 A3 和 B4 以创建 A4。

Merging

两个功能分支正在合并到主干
  1. 从分支 A(主干)中的版本 A1 开始。
  2. 从 A1 创建分支 C,进行一些更改以创建 C1。
  3. 进行更多更改以创建 C2。
  4. 切换回 A1,进行一些更改以创建 A2。
  5. 从 A2 创建分支 B,进行一些更改以创建 B1。
  6. 进行更多更改以创建 B2。
  7. 不要对 B2 进行更改,而是将 C2 合并到 B2 中以创建 B3。
  8. 进行更多更改以创建 B4。
  9. 切换回 A2,进行一些更改以创建 A3。
  10. 不要对 A3 进行更改,而是将 B4 合并到 A3 中以创建 A4。

为了创建 B3,没有对 B2 进行更改,与 B1 到 B2 或 B3 到 B4 不同。B3 的变更集是通过将 C2 合并到 B2 来创建的。合并 A3 和 B4 时也是如此。

提交/修订

进行一次提交会创建一个新的修订(版本),即您代码在那一刻的快照。这个快照不像完整的备份,它更像是一组指令,用于重新创建该版本,起点和变更集。

因此,您正在开发一个名为 `FootBook™` 的新产品,并想添加一个名为 `ToeCracker™` 的功能。所以您将这个过程分为三个步骤:`Load`、`Aim` 和 `Fire`。完成第一个步骤(`Load`)的开发后,您决定保留迄今为止进度的永久记录。您进行一次提交。这会在版本控制数据库中固定一个记录,记录项目在那一刻的状态。然后您可以开始处理 `ToeCracker™` 功能的 `Aim` 部分。如果第一次尝试 `Aim` 完全失败,您可以通过拒绝迄今为止所做的所有更改(或只是一部分)来闪电般地恢复到良好的状态,而无需去寻找您三周前所做的备份并手动拆解所有内容。

一旦您成功完成了 `Fire` 功能(并且 `ToeCracker™` 完成了),您就可以将当时进行的提交合并回您的主干。`ToeCracker™` 现在是您主干的一部分,您将其 FTP 到实时服务器,所以下次更新 `FootBook™` 网站时,`ToeCracker™` 功能将可供所有人尝试。

Commit

创建 ToeCracker 功能

它还允许您暂时停止处理 `ToeCracker™`,并在另一个分支上开始处理另一个功能,然后再切换回 `ToeCracker™`,而不会丢失您所做的任何更改,也就是说,提交不一定是一个结束,它们可以只是一个方便的停靠点,您可以在每晚睡觉前进行一次,没有人关心。他们只关心该分支的最终提交。

暂存

完成 `Load` 后,您开始处理 `Aim` 并对三个文件 A、B 和 C 进行了更改。您准备进行提交,但对 C 的更改与 `Aim` 关系不大,它们应该属于 `Fire`,所以您不想包含它们,您想将它们保存到下一次提交,在您完成 `Fire` 后。

很简单,每次提交之前,您都需要暂存(staged)您想要包含在提交中的文件(已更改的文件)。如果您不暂存其中一个,它会保留其更改,但提交会忽略它们,也就是说,提交使用 C 的未更改版本(来自前一个版本),但您并没有丢失您的更改,只是推迟了提交它们;所以它们不会进入数据库中的那个版本,它们将进入一个稍后的版本。

只需确保在提交之前接受(accept)更改,即使它们没有被暂存,否则您将丢失它们,尽管您通常会收到警告,并有机会取消提交。

推送和拉取

如果您是独自工作,尤其如果您将只在本地工作,那么您*很可能*根本不需要担心这一点。除非您使用克隆作为分支的一种方式。

由于我没有使用过远程存储库,我可能需要被纠正。

所以,假设 Sam 想帮助处理 `FootBook™`。因此,您现在需要使用远程存储库,以便您和 Sam 可以相互共享更新,并且您在 GitHub 上启动了一个项目。当您在本地存储库中完成了一个新功能后,您将该更改*推送*到远程存储库。然后 Sam 可以将其*拉取*到他的本地存储库。现在,您两人都拥有项目(以及它如何更改的所有历史记录)的完整最新副本,而无需将 U 盘邮寄给彼此。

Pushing and Pulling

在存储库之间推送和拉取

您只会在不同的存储库之间进行推送和拉取。

分叉

分叉(Fork)本质上是一个永久性分支,通常会移动到不同的存储库。您可以抛弃分支这个术语,直接称之为临时分叉。

所以您和您的朋友 Sam 正在处理 `FootBook™`。您两人都一直在开发 `FootBook™` 的功能,并将您本地存储库中完成的功能*推送*到远程存储库,就像我们上面讨论的。然后,Sam 喝得大醉,把啤酒泼在你身上,睡了你的伴侣,并告诉你你们永远不会再是朋友了。`FootBook™` 完蛋了。

所以您将远程存储库中的所有更改*拉取*到您的本地存储库(这样您就拥有了一个包含 Sam 所有工作的完整最新副本)。您使用它创建了一个名为 `AnkleBook™` 的新项目。历史书在记载 `AnkleBook™` 的巨大商业成功(及其亿万富翁创始人)时,会提到它起源于 `FootBook™` 的一次*分叉*,而原始项目在那个风流醉汉手中失败,一事无成。

在您对 `FootBook™` 的新代码副本进行任何更改之前,`AnkleBook™` 存储库是 `FootBook™` 的一个克隆,而您用来创建新 `AnkleBook™` 存储库的机制就是*克隆* `FootBook™` 存储库。克隆是如何在单独的存储库中创建分叉的。

克隆

通过克隆分叉一个项目

Forking and cloning

您也可以将克隆用作分支模型(一种重量级的分支模型)。创建一个克隆,进行更改,提交它们,然后将克隆*拉取*到您的原始存储库。这被称为重量级,因为它创建了两个相同东西的大型副本,两组文件夹和两个数据库。

这也是您获取现有项目(例如 Linux 内核)的第一个副本,并想参与其中。所以,以我们的例子来说,在失去 Sam 后,您请 George 参与。George 克隆了远程 `AnkleBook™` 存储库,并在他的新本地存储库中开始工作。

所以您和 George 一起处理 `AnkleBook™` 一段时间了,您开发了一个名为 `FootLinker™` 的新功能。在开发 `FootLinker™` 时,您修改了 `ligament.cs` 文件。不幸的是,Sam 在开发 `ShinLinker™` 功能时也修改了这个文件。当 Sam 将您的 `FootLinker™` 功能*拉取*到他的本地存储库并尝试将其与他的 `ShinLinker™` 功能合并时,VCS 会因为同一个文件有不同的更改而出现问题。谁赢?

合并冲突

当您在 `ligament.cs` 文件的不同部分进行更改时,VCS 通常可以自动为您解决。然而,如果您两人都对同一行代码进行了不同的更改怎么办?此时,您通常必须介入,帮助VCS选择如何处理,有时还要收拾残局。

即使您独自工作,也可能发生同样的事情。如果您存储库中有两个分支?因为您同时处理两个新功能(因此,*您*可能对同一代码进行了冲突编辑),您可能会给自己造成合并冲突。这没什么不同,过程相同,只是您必须与自己争论,而不是再次被 Sam 泼啤酒。

顾名思义,`Diff` 就是*差异*,通常指的是一个工具或该工具的输出,它通常内置于VCS本身或作为外部插件可用。VCS 使用它来精确地找出旧版本和当前版本的文件之间有什么变化,甚至同一文件在两个不同分支之间的变化。它们非常聪明,即使您在开头做了一些更改,例如多加了一行代码或两行,它也不会认为下面的所有内容都发生了变化,它会计算出来。所以它确实只识别实际的更改,编辑过的行、删除的行和添加的行都会被发现并被视为相应的更改。

差异

我认为 diff 工具的输出也是 VCS 记录更改的方式——也就是说,它创建一个变更集,所以变更集比项目的一个完整备份要小得多。它用于处理自动化的冲突处理,以及可能我还没有发现的所有其他令人兴奋的功能。这些东西真是太棒了。

我们开始进入细节了,这些术语在不同的VCS选项之间肯定有不同的解释。它们提供了轻量级分支的方法,记录重要的里程碑(小版本和主版本)等。现在可能不太重要。

标签、标记、书签等。

值得指出的是,我的经验是基于开发基于 PHP 的网站,而不是使用像 Visual Studio 项目这样的 VCS,所以我不能保证这些原则都适用,但感觉它们应该是适用的。

我的用例

特别是,我遇到的导致我开始研究版本控制的问题是,我手动版本控制模型如下:

保留整个源代码的两份副本,一份放在名为 `prod`(生产)的文件夹中,一份放在名为 `dev`(开发)的文件夹中。

  1. `Prod` 应始终代表实时服务器上的内容,而 `dev` 是我进行工作的地方,直到准备好上线。
  2. 每次更新准备上线时,我会将 `prod` 文件夹压缩成一个版本并存储在 `archive` 中,然后将 `dev` 复制到 `prod`,再将 `prod` FTP 到实时服务器。
  3. 这工作正常,直到我需要同时进行内容更改**和**功能添加。如果我还在开发一个功能添加的中间阶段,我如何使用我的手动版本控制模型来添加一些新内容?我即将遇到一个保持网站更新的重大障碍,因为我正处于一个相当大的功能增强的中间阶段。

最后,值得注意的是,我还没有(在任何程度上)测试过它们的存储库托管选项,我尝试过,但不是真的用过——只有我一个人,我并不真正需要分布式部分,只需要版本控制部分。所以 Subversion 可能没问题,但它似乎不是未来,而且所有 DVCS 都声称像多开发者环境一样适合单用户场景。

我在网上读了很多东西,你会很快意识到你的主要选择可能是 BazaarGitMercurial。当然还有其他的。然而,对于版本控制的新手来说,网上很少有指南,大多数文章都基于您已经在使用并且熟悉 VCS 的前提,几乎总是 Subversion,这使得找到对我有用的指导非常困难。让我选择 Bazaar 作为我的第一个选项的特定页面是 Smashing Magazine 的这篇。我没有理由相信这篇特定网站的文章比其他文章更好,除了它的写作风格似乎比其他大多数文章更符合我的知识水平和需求。

比较VCS选项

所以,我开始使用 Bazaar,因为它的描述对我来说更符合。特别是,文章说:

'*Mercurial 是为大型项目设计的,很可能超出了设计师和独立 Web 开发者的范围*'; 暂时忽略 Mercurial。

  1. '*然而,Git 不像 CVS 或 SVN 那样容易上手,所以对初学者来说更难使用*'; 同样,我们暂时忽略 Git。
  2. 而对于 Bazaar,关键的一句话(对我来说)是‘*如工作流程所示,您可以使用它来适应几乎任何用户和设置的场景*’,听起来更像那么回事。
  3. 现在我有自己的、截然不同的观点来描述它们,请继续阅读……

Bazaar Итак。

Bazaar Итак。

而且由于我习惯于使用两个不同的副本(prod 和 dev),我想拥有两个克隆,而没有使用分支(令人遗憾)。

Bazaar和Launchpad

Bazaar 是一个由 Canonical 支持的开源项目。许多知名的开源项目使用 Bazaar 及其相关的远程服务器 Launchpad,例如 Ubuntu、Debian、MySQL、Bugzilla 等,因此它显然有一些良好的支持,因此可能相当强大,但对于新手来说呢?

Bazaar Explorer Main Window

Bazaar Explorer:看起来足够友好

在 Windows 上,有一个非常不错的 GUI 客户端 Bazaar Explorer。独立的 Windows 安装程序还提供了添加 TortoiseBzr(Shell 扩展 - 类似 Explorer 右键菜单)、Git 集成和 Subversion 集成以及其他一些对更专业用户可能很重要的选项。

我的主要测试是在 Bazaar Explorer 上进行的,虽然我上面说“非常好”,那是在“感觉上是否友好的地方?”的视角。一旦我开始尝试使用它,我就很快卡住了。仅仅弄清楚如何将我脑中的想法转化为 Bazaar 的语言,以便我能够按下正确的按钮就很难了。我像世界冠军手中的溜溜球一样来回查看文档。哦,而且文档有点稀疏。总的来说相当令人沮丧。

例如,如何创建一个新项目。Bazaar 似乎称项目为存储库,但我不太确定。

Bazaar Create New Project

Bazaar Create Project:有人知道我想要哪种工作区模型吗?

说真的,如果那些提示说“*如果你flibble你的flobble,你就能创造一个flooble*”,那我对发生了什么会有一个更好的想法。我是否想移动现有的文件?或者创建一个工作签出?完全不知道。

到目前为止的评价公平吗?嗯,可能不是,Bazaar 是我第一次尝试版本控制,所以应该期望会遇到一些困难,但对于一个被描述为‘*可以适应几乎任何用户和设置场景*’的工具,我不应该如此艰难地斗争。用于独立工作的文档,Solo Workflow 说:

  1. 创建项目。
  2. 记录更改(在此过程中进行提交)。
  3. 浏览历史(查看*提交*的评论或两次提交之间的更改,即*变更集*)。
  4. 打包发布(*标记和打标签*)。

**真的吗?** *您真让我震惊!* 我该怎么做?一片寂静。即使是非 Canonical 的指南和文档也没有太大帮助。我花了很长时间认为是我有问题(而且可能仍然是),但最终放弃了。我需要更多的帮助,要么通过工具的直观性,要么通过非常好的文档,Bazaar 都无法做到。

关于 Bazaar 的另一件事是 Launchpad 集成,这并非我最主要的需求,但我确实尝试过。一旦在 Launchpad 上创建了一个项目,它就会永远存在,即使它里面没有任何东西,因为他们不希望人们删除可能被他人依赖的项目。我理解,在开源世界中,这是一个关键的关注点,但我的项目里面没有任何东西!非常令人沮丧。所以,很难在*沙盒模式*下使用 Launchpad,同时让您熟悉它并尝试其功能,学习窍门等等。

回到公平地讲,我之前说过,一些相当大的公司和项目都在使用 Bazaar 和 Launchpad,所以它肯定有比我发现的更多的优点,但这主要是关于为初学者选择 VCS,对我来说,Bazaar 不是它。也许一旦我更加熟悉 DVCS 之后,然后可以应用通用知识来使用 Bazaar,事情会变得更容易,我可能会有一天冒险尝试。

Git和GitHub

好的,接下来是 Git。Git 得到了如此多的关注,它一定值得一试,而且无论如何,Mercurial *不适合独立 Web 开发人员*,所以我只剩一个选择。

Git 的历史到处都是,最初由 Linus Torvalds 开发(显然是在与 BitKeeper 发生了一些争执之后,我不知道,我没有详细了解)。现在由一支庞大的军队维护,并被一些知名公司使用,微软、谷歌、Android、Facebook、Rails,等等。所以再次,它一定有什么优点,但对新手来说呢?

在 Windows 上安装 Git 会提供 Shell 集成(就像 TortoiseBzr 为 Bazaar 所做的那样)和一个 GUI,它富有想象力地命名为 GitGUI。天哪,那个东西太稀疏了!它绝对没有杂乱,信息量尽可能少,而且看不到右键菜单。那种训练方式可能对空手道小子有效,但我没有宫城良田来帮忙。显然是为那些已经确切知道自己在做什么的人设计的。那不是我。

GitGui Main Window

GitGui:嗯,现在呢?我还需要再刷一次篱笆吗?

并且修订历史(graphlog)的可视化并没有好多少。它本身并不差,只是用户友好性似乎不是优先级列表中的首要考虑因素(似乎),功能优先于形式。所以 GitGui 很快就被丢弃了。

GitGui Revision Visualisation Window (Graphlog)

也许它实际上并没有那么糟糕

在网上搜索后,我找到了 SmartGit,一款商业 Git 客户端,对非商业用途免费。据称,您也可以将其与 Mercurial 和 Subversion 一起使用。

SmartGit Main Window

SmartGit:好的,这感觉更受欢迎一些。

SmartGit 拥有比 GitGUI 更舒适的工作环境,所以您一开始不会感到完全不知所措。营销宣传甚至说‘*SmartGit 帮助 Git 和 Mercurial 的初学者快速上手*’。我非常愿意相信他们。然后我遇到了一个巨大的障碍,如何实现我期望的操作模型,即克隆。无论我阅读 Git 手册还是备受推崇的在线 Pro Git 书籍,都没有帮助我走出这个困境。

然而,我并没有那么轻易放弃,所以我决定先玩一会儿,看看*提交*是如何工作的,并尝试与 GitHub 集成。是的,很快又陷入了斗争。您必须担心*暂存*和取消暂存,然后才能提交——这在 SmartGit 中感觉不是那么好地集成——所以我经常忘记。为了 Git 和 SmartGit 的辩护,所有这些概念都很容易理解,但它只是没有感觉像是工作流程中的自然部分,也就是说,即使是一个傻瓜,该工具也不会帮助他做正确的事情!

修订历史(graphlog)窗口比 GitGUI 的更具吸引力。

SmartGit Revision Visualisation Window

SmartGit修订历史可视化窗口(Graphlog)

这公平吗?也许如果我更早地切换到使用*分支*,我会在 Git 和 SmartGit 上取得更大的成功,但就像 Bazaar 一样,学习曲线,即使只是语言上的,也很陡峭,非常陡峭。正如我在上面指出的,我在 PHP、VB 和 .NET 上已经有了足够的学习曲线,感觉不需要再承担另一个,所以它被放弃了。

Mercurial和BitBucket

Mercurial 是另一个开源项目,它与 Git 出于相同的原因(我仍然没有深入了解细节)而创建,据称它在 Git 出现几天后就开始了(无论如何),并且虽然 Linux 内核开发转向了 Git 而不是 Mercurial,但 Mercurial 仍然可以声称一些大名字,尽管这次是作为赞助商(更难确定哪些大项目在使用 Mercurial),赞助商包括 Google、微软和 Mozilla 等。

TortoiseHg Window

TortoiseHg:有很多东西要处理,但并不难弄清楚该做什么。

因此,怀着一丝忐忑,因为据说这比其他两个更难,我安装了 Mercurial。作为标准的 Windows 安装程序,它附带了 TortoiseHg。现在,这个版本的 Tortoise 与为 Bazaar 编写的版本不同,因为它也是一个 GUI,而不仅仅是一个 Shell 扩展(TortoiseGit 也只是一个 Shell 扩展而不是 GUI)。

好的,所以 TortoiseHg 是一个非常舒适的工作场所,有点像 SmartGit。不要过分强调这一点,但对我来说,像 GitGUI 与 SmartGit 或 TortoiseHg 之间的区别,就像旧的基于 DOS 的文字处理器与今天的 MS Word(或 LibreOffice)之间的区别。它确实有如此大的差别,对于初学者来说,这可能是在能够做事和专注于您真正喜欢的事情——编码——之间产生巨大差异的关键,对于初学者来说,这很可能是一个爱好,而不是一份工作,我希望继续做有趣的部分。

但实际做事呢?嗯,第一步是能够*克隆*并轻松做到。宾果,我在原始版本上做了一些内容更新,在此过程中进行了*提交*,当准备好时,将其 FTP 到实时服务器,搞定。同时,我正在克隆上忙于处理那个功能。功能完成后,我将更改*拉取*到原始存储库(我在那里进行了内容更新),然后瞧,功能*变更集*(及其完整历史记录)就成为了我原始存储库的一部分,作为一个大的*分支*。现在只需将功能*分支*与代码合并,其中包含内容更新,瞧,搞定(又一次)。

在上面我展示的图片中,您可以看到修订历史(graphlog)一直都在,我觉得很方便。要在创建新提交(如所示)和查看如果您立即进行提交将包含什么之间切换,只需单击顶部的工具栏按钮。然后屏幕的下半部分相应地改变。而且布局在两个视图中都保持不变,太棒了,有人考虑过这一点。布局(在下半部分)如下:左侧是文件,右上角是提交注释,右下角是所选文件内的详细更改。您可以看到

  1. 修改的文件是*蓝色*的,并标有*M*
  2. 删除的文件是*红色*的,如果我还没有接受删除,则标有*!*,如果接受了,则标有*R*
  3. 我已接受添加的文件是*绿色*的,并标有*A*
  4. 我*未*接受添加的文件是*粉色*的,并标有*?*
  5. 已暂存的文件在复选框中带有勾号。
  6. 提交时用于添加此版本注释的空间,显示在右上角。
  7. 所选文件(*scoresmenu.php*)的详细更改显示在右下角。

比我之前用过的任何东西都要好得多。

看到从克隆拉取到原始存储库只是创建了一个分支,让我更多地思考分支,我现在完全使用分支。所以我可能有一个*默认分支*,一个内容更新分支(当我需要时,它们通常是短暂的)和一个功能分支(或两个,或更多)。我可以独立地处理它们,轻松地在它们之间切换,轻松地将完成的内容更新或新功能合并到默认分支,将其 FTP 到实时服务器,然后就完成了。我也可以同时运行多个功能分支。

* 在 Mercurial 中,您始终有一个默认分支,除非您使用书签或匿名分支(我没有)进行分支,那么对我来说,默认分支的尖端始终与实时服务器相同,这很方便,即我将 Mercurial 的默认分支用作*主干*。

这公平吗?很难确切地说它比 Git 更好,因为我没有尝试过 Git 的分支功能,但我仍然感觉 Mercurial 在学习曲线方面有些地方更容易,也许如果我今天回到 Git,我会发现它更容易。它会比 Mercurial 容易或更好吗?不确定。可以说 Git 可能更常见,任何您想要参与开源多开发者开发的愿望,用 Git 进行的可能性比 Mercurial 大,但对我来说,我猜想这是一个非常平均的选择,双方都有优缺点。也许使用 Mercurial 开始,我认为您会发现切换到 Git 很简单,反之亦然也可能很轻松,但也许 Mercurial 更适合“*学习窍门*”。

同样值得注意的是,对于“*是否公平*”的讨论,我所辩论的很多内容可能取决于 GUI 而不是底层的 VCS,但我确实认为这是初学者体验和学习曲线中非常重要的一部分,所以我认为它(在本*讨论*的上下文中)作为判断的组成部分是相关的。而 TortoiseHg 在这方面对我来说是一个真正的赢家。

最后关于 Mercurial:我提到了 Git 的*暂存*和取消暂存,并且发现它没有感觉像是工作流程的一部分(无论是基于 GUI 还是 VCS),嗯,Mercurial 本质上也有同样的东西,更改与前一次提交的比较(在 TortoiseHg 中)被高亮显示,您接受或拒绝它们,然后每个更改的文件都有一个复选框,几乎复制了 Git 的暂存和取消暂存,但它只是更明显和自然地使用。想接受所有更改但只提交一部分,勾选您想提交的,进行一次提交,然后继续工作,已接受但未提交的那些就成为您下一次提交的一部分(如果您愿意,或者进一步推迟)。在我的例子中,我大部分时间都提交所有更改,所以我只勾选所有(这可以通过一次单击完成)。

哎呀,那不是最后,您还会得到 TortoiseHg Overlay Icon Server,它在标准的 Explorer 图标上提供视觉图标叠加,表示文件在您的存储库中的状态,未更改、添加、更改等,非常不错(我认为 TortoiseGit 也有类似的功能)。我还将存储库上传到了 BitBucket(它托管 Git 和 Mercurial 存储库),足够简单,在我看来比 GitHub 好或差。

我写了比其他两个更多的关于 Mercurial 的内容,我使用它的时间更长。原因就在于此。

总结比较

很明显我更喜欢 Mercurial,我感到更自信,并且发现它易于使用,它没有分散我进行网站开发的注意力,当我犯错误时(无论是版本控制错误还是编码错误),很容易撤销,您甚至可以回滚*提交*(如果您足够快地意识到的话,您可能也可以在其他版本中做到,我没到那一步)。

我的判断中可能存在 GUI 的过度影响,但对我来说,那很重要,我认为它对许多初学者很重要,他们不是来自命令行背景,也没有先前的版本控制经验。这可能是我偏爱 Mercurial 的最大原因,因为 TortoiseHg 对我和我奇特的脑袋来说更好。

也可能受到我思维方式的强烈影响,也许 Mercurial / TortoiseHg 就是*更适合我的脑袋*,而不是其他,谁知道呢?

我强烈建议初学者尝试 Mercurial,特别是与 TortoiseHg 一起使用。也尝试一下其他的,*您*可能会发现它们对*您*更好。

对于 Bazaar,我无法说出 Bazaar Explorer 的确切问题,现在回头看,它似乎试图过于简单,几乎像一个向导工具,而不是一个不显眼的、与您协同工作的工具。而且 Launchpad 让我非常恼火。

对于 Git,我认为它比我最初发现的更容易,特别是现在我对版本控制有了更好的了解(特别是*分布式*、*以分支为中心*的 DVCS 的好处,即使是单用户使用),使用的术语和概念等,但我也认为它的学习曲线比 Mercurial 更陡峭,特别是如果您使用 GitGUI(打了个寒颤)。GitGUI 与我刚才描述的 Bazaar Explorer 完全相反,但不是以一种好的方式。

我后来又回去使用了 Git(为了创建上面的截图),我确实发现分支比以前容易了,而且我确定我最终会记住暂存和取消暂存。然而,我无法克服它的学习曲线比 Mercurial 更陡峭的观念,它不像我发现的 Mercurial(配合 TortoiseHg)那样直观。

尝试一下,即使您的项目没有迫切需要版本控制(也许您认为它太小太简单了),您可能会发现它在您意想不到的方式下很有用。即使您只在本地工作,从未打算使用 BitBucket 或 GitHub 或参与开源项目,那也不是必需的,能够追溯您的更改,分支不同的功能,并将内容和功能(至少对于网站来说)分开是非常方便的,比我开始时意识到的要多。

其他说明

可以说,我现在有点离题了,因为这本应是关于选择第一个 VCS 的,但我认为这些笔记足够接近主题——帮助那些从未用过版本控制的人入门——所以我并不介意,希望您能原谅我。

分支

这是最初让我感到困惑的一个领域,也是我最初想*克隆*的原因之一——我只是不想尝试同时学习*分支*以及其他所有东西。这个概念听起来很简单,但有很多分支模型和每个 VCS 中的不同分支方式——不仅仅是两个 VCS 之间的区别,实际上是 VCS 内部的不同方式——我到底想用哪一个?这篇关于 Mercurial 分支的指南非常有帮助,但当您从未做过任何 VCS 时,它会让您望而却步,因为您突然有了太多您还不完全理解的选项,至少不深入。

我能给出的唯一建议是:从简单开始,在 Mercurial 中,您只需创建一个命名分支(很容易做到),忽略其他分支方式——在 Mercurial 中,这就是 Steve Losh 所描述的“*通过命名分支进行分支*”。它还有一个优点,对我来说,*主干*(默认分支)的尖端始终代表实时服务器,我从不直接在其上工作,我总是在命名分支上工作,并在准备好发布该功能或内容更新时将其*合并*到主干——尽管这已经进入了我个人分支模型的细节,我只提一下,因为我发现以这种方式工作时,很容易遵循我正在做的事情!

话虽如此,我真的想学习其他分支方式,包括 Steve 没有提到的 Mercurial 的补丁队列功能,但命名分支很容易理解和使用。尝试一下。

错误修复和分支

关于分支的更多说明,以及我仍在尝试弄清楚如何做的事情。

好的,假设您有您的*主干*和一个命名功能*分支*,其中包含几个*变更集*(但尚未完成)。然后您在实时服务器上发现了一个错误。很容易从主干的*尖端*创建一个新的命名分支用于修复错误,解决错误,将该分支*合并*到主干并将其 FTP 到实时服务器。任务完成。但是如何将这个错误修复带入我的功能分支?我可能想避免以后出现*合并冲突*,通过将错误修复带入命名功能分支,而不是在功能完成后(当我想将它与主干合并时)再解决*合并冲突*。

Bug fixes and feature branches

如何将这个错误修复带入功能分支?

我还不知道如何做到这一点,我认为如果我在“*专业的*”DVCS 环境中与多个开发人员一起工作,那么我只需要*拉取*相关的变更集从错误修复分支到我的本地*存储库*并与我的代码合并,在合并时解决合并冲突。然后当我将我的功能分支*推送*到远程存储库时,错误修复就已经在里面了,我不会出现合并冲突。但我不知道如何在本地工作中复制这一点。我有一种感觉,Mercurial 的补丁队列可能会帮助我,但我不知道,我也找不到这个问题的答案。唉!

也许这是 Mercurial 和 Git 之间的一个区别,我怀疑 Git 的支持和知识稍微多一些,因为社区可能大一个数量级,因此论坛上的建议等。(我确实说了更多/更好而不是仅仅更多,但我没有依据假设更多=更好!)

分支和合并 - 冲突

我曾经担心的一个问题,并且它确实咬了我一次,就是*合并冲突*——也就是说,当您在两个不同的分支中对同一代码进行了冲突编辑,而这些冲突后来需要合并时。我犯了一个非常严重的错误,幸运的是 Mercurial 有一个非常易于使用的回滚功能,嘿,我回到了尝试合并之前的状态,然后我可以弄清楚如何管理它,我最初是手动处理的,然后再次尝试合并,也就是说,我手动编辑了每个版本中的相关文件,使它们相同,所以没有合并冲突。

后来的合并冲突是我使用内置*diff*工具处理的,它不像 TortoiseHg(或 SmartGit)那样用户友好,但一旦您开始习惯它,它也不是那么糟糕。我最初的犹豫部分原因是我在凌晨 2 点尝试使用合并工具时喝醉了(实际上喝了很多),不太聪明!您还可以插入许多替代的 diff 工具,这样您就可以尝试几个,直到找到一个“适合您的脑袋”的。我相信对于大多数 VCS 来说都是这样,不仅仅是 Mercurial / TortoiseHg。

本地工作

正如我之前提到的,我的大部分工作都是在本地完成的,而不是通过 GitHub、BitBucket 等托管的远程*存储库*完成的。虽然 DVCS 的一个重要之处在于*分布式*部分,而不仅仅是版本控制部分,但我发现它对于本地版本控制完全有用,我(到目前为止)没有因为不使用远程存储库而丢失或妥协任何东西。唯一的潜在例外是我上面提到的关于在*分支*之间移动特定*更改*的观点,但我怀疑在本地工作时也有办法做到这一点,只是我还没有弄清楚。

另一个选择是,如果您在家中有 NAS 设备,可以在上面安装 Git 服务器或 Mercurial 服务器。然后,您的项目就不在本地驱动器上,而是可以将其托管在您自己的服务器上,*克隆*服务器存储库到您的本地驱动器,并将本地更改*推送*到您的服务器。然后,如果您通过防火墙暴露该服务器,您就可以从世界任何地方访问您的“远程”项目存储库。

IDE集成

由于我们许多人都使用 IDE,这是一个不错的选择,并非所有人都需要它——我现在不使用它——但很高兴知道您有选择。Git 似乎与 Visual Studio、NetBeans 和 Eclipse 集成。Mercurial 看起来也差不多,VS、Eclipse 和 NetBeans。

我不使用 Eclipse 或 NetBeans,但在 VS 中快速搜索扩展库会显示 Git 和 Mercurial 的选项。而 Google 搜索结果的第一页对这两个 VCS 的说法与我上面列出的相同。但我没有测试过任何一个;我使用 TortoiseHg 已经足够轻松了。

Bazaar 在其 Wiki 上有一个专门列出*IDE 集成选项*的页面,它似乎有很多(包括 VS),但 VS 扩展搜索只显示了零个——同样,我也没有测试过任何一个。

起初,我认为 IDE 集成对我非常有益,但回想起来(至少对于业余级别的项目来说),它并非必需,而且由于 VCS GUI 工具(如 TortoiseHg)是专门为此任务设计的,它比尝试将其钩入 IDE 效果更好,并且会不可避免地影响信息的呈现方式(即使只是屏幕空间方面)。

如果您测试了其中的任何一个,请告诉我(或写您自己的文章)。

跨DVCS互操作性

我没有测试过互操作性部分,但请记住,在阅读阶段,我曾评论过所有这些 DVCS 工具相互操作以及与 Subversion 的能力——每个工具在此方面的管理能力差异很大,从糟糕到出色(“*如同魔法般工作*”这句话给我留下了深刻的印象)。然而,如果您选择了一个工具,然后又参与了一个运行在不同 VCS 上的项目,知道您并非完全迷失方向,您可能可以使用您偏爱的 GUI 来处理一个由不同 VCS 管理的项目。使用 Git 的 SmartGit?想参与一个使用 Mercurial 的项目?SmartGit 应该能应付,这样您就能最大限度地减少头疼,您不需要在参与之前“学习”Mercurial。

有一篇有趣的博客文章,作者是 John Szakmeister。他谈到了每个工具如何能够访问并与其他工具以及 Subversion 良好地配合,我无法补充更多,而且您肯定会找到关于同一主题的其他博客和文章。然而,对于初学者来说,只有当您决定参与一个托管在与您自己工作所选 VCS 不同的 VCS 上的多开发者项目时,它才真正重要,因此我无法想象它相对于我触及的其他一些要素有多重要,至少直到您远远超过需要我建议的阶段。

如果您阅读了那篇文章,那么我想指出这一点:他对 Mercurial*分支*的评论与我的截然相反,我不确定我是否理解他的推理,即分支存在于不同的文件夹中。我完全不明白(尽管他可能比我更有信誉和知识),我有许多命名分支,只有一套文件夹加上*存储库*数据库。当我想要切换分支时,我只需 `Update` 到那个分支,然后我的单一文件夹集就会神奇地包含所有正确的文件(根据需要删除、添加和更改)。也许这与专业开发或多开发者项目有关,而我只是看不到,但即使那样,我也认为*分布式*VCS 的要点是每个开发人员都有一个本地副本,进行更改和*提交*,然后与服务器同步,所以每个开发人员都可以处理他们需要的任何分支。也许有一天我会知道。

这些只是我发现一些有价值的建议、评论和指导的一些地方。

  • 一个 StackExchange 讨论,关于选择 VCS,阅读 dukeofgaming 提供的顶层答案,一些可能对您有帮助的有趣图片。
  • Joel Spolsky 的 Mercurial,以与 Subversion 的比较开始(正如许多人所做的那样),但您可以跳过它。
  • Steve Bennet 不喜欢 Git。这可能有助于解释为什么我发现 Git 很难掌握。一个有趣的评论(2012 年 8 月 3 日更新中的第 5 条)说:**改用 Mercurial!**当然,如果您是幸运的人,可以选择项目使用的 VCS。Mercurial 似乎得到了很多喜爱,但使用量不大,奇怪。

关注点

仅仅阅读这类东西并不能帮助*您*找到*您*的答案,您必须亲自动手尝试每种选项,找出适合您的。祝您玩得开心。

历史

  • 版本 1:原始文章
© . All rights reserved.