Git 故事连载

孙以义著

1. Git是什么?

leave a comment »

Git 是 Linux 的创始人 Linus Torvalds 开发的开源和免费的版本管理系统,也称源代码管理系统(Source Code Manage, SCM)。它的官方网站是 Http://git-scm.com

2005 年的时候 Linux 核心开发小组和当时的他们的版本管理系统提供商产生了分歧。他们不能再使用原有的版本管理系统了。当时 Linus 环顾宇宙之内竟然没有一个能满足自己需求的版本管理系统可用。于是他毅然决定自己动手开发一个!这就是 Git。时至如今,Git 已经成为许多著名系统的版本管理系统。比如Linux 核心,Eclipse,Android,Ruby on Rails,PostgreSQL,jQuery …… http://en.wikipedia.org/wiki/Git_(software)

Git 在英文中原意是蠢货或者笨蛋。Linus 用了这么一个名字反映出他是个个性很强的人。他在2007年的 Google Tech Talk 会议上介绍 Git 的时候用了非常强悍的语言数落了一些当时著名的版本管理系统 CVS 和 Subversion。 全世界大概也就 Linus 够这个资格这么说话吧。http://www.youtube.com/watch?v=4XpnKHJAok8

我觉得 Git 是个很酷的名字。比起起来开源系统的名字,什么水银(Mercurial),什么集市(Bazaar)等等,Git 要响亮得多。当然这不是我喜欢 Git 的原因。我喜欢 Git 是在我使用 Git 一段时间后觉得它实在是好。具体怎么好法,我准备写个 Git 故事连载,一一记录下来和大家分享。

在网上已经有许多不错的介绍 Git 的资料。它们多是在 Linux 或者 Mac OS 下用命令行。看不到几页就会犯困。我的Git故事连载特点是全部是在 Windows 下使用 Git,而且尽可能多的图形界面 (GUI)。这点在前几年不大可能办到。最初Git 的开发者们对于 Windows 下运行的 Git 很不以为然。网上搜索引擎检索出来的结果有相当一部份都说Windows下不适合用 Git。各位要注意的是搜索引擎里过时的内容可不少。看网上的文章千万要注意它的发布日期。2010年以前的评价Windows下用Git的大都可以不用浪费时间去看。我的Git故事连载以后也会过时的,但是现在是最新鲜的。

Advertisements

Written by yysun

一月 31, 2011 at 10:46 下午

发表在 git

Tagged with

2. 怎样安装 Git

leave a comment »

与网上现有不少资料就事论事逐一介绍Git的功能和命令不同,这里主要讲Git用法背后要解决的问题,以及对这些问题的衍生思考。所以是讲故事,而不是给你罗列Git的好处。让你不仅知其然,而且知其所以然。我要讲的第一个集故事就是如何要把Git安装起来。

Git的官方主页上可以连接到 Git for Windows下载专区。这里有好几个文件。这里简单介绍一下:

  1. 以Git-开头的文件。它是Git for Windows的安装文件。它象大多数Windows程序那样把Git装到C:\Program Files 目录下,注册好Git程序,也能让你从控制面板中删除。
  2. 以PortableGit-开头的文件。所谓Portable就是我们常说的绿色版。释放出来就能使用,不需要修改系统文件或者修改注册表。
  3. 以msysGit-开头的文件。它们是完整的开发环境,包括了Git的源程序和GNU C编译器。它可以用来把Git的源程序编译成可执行程序。

一般用户应该用Git-开头的安装文件。但是先不要安装它,继续往下读。

在前文中提到,本故事连载主要讲在Windows下使用Git。好像一些耍酷的Linux用户只用命令行那样,我也可以耍一下酷,在Windows下我可以全部只用图形化界面。

Git Extensions 是Windows下的开源的Git图形界面。有了这个工具,所有Git在Windows下不好用的抱怨都过时了。它是用 Windows Forms 技术开发。里面有很多技术可以借鉴学习,也许将来可以来一集故事剖析剖析它,看看如何开发 Git的扩展工具。Git Extensions 的下载区(也有好几个文件。我们要用GitExtensionsXXXSetupComplete.msi。其中XXX是版本号。由于这个工具更新很快,版本号会不断变化。有Complete的这个安装文件包括了Git for Windows,Git Extensions 和 KDiff3。这是个三合一的安装程序。其中KDiff3是个必须的源程序合并工具,在以后的故事里你会看到它用处很大。

这一集的核心思想就是用Git Extensions是目前Windows下一个出色的Git图形界面。它的安装文件可以一次把三个工具都安装好。安装好后,建议阅读它的文档学会基本操作如何创建仓库(initialize repository),如何提交程序文件进仓库(commit)等等。

Written by yysun

一月 30, 2011 at 12:13 上午

发表在 git

Tagged with

3. 与 Visual Studio 集成

leave a comment »

工欲善,必先利其器。Windows 下用 Eclipse开发程序,Eclipse 的 EGit 插件提供了 Git 的支持。

如果用 Visual Studio,你一定要安装个 Git Source Code Control Provider 插件。方法是用菜单 Tools | Extensions Managers…,检索 git 然后下载安装。

clip_image001

安装以后,Git 管理的程序项目里文件的状态就会在 Visual Studio 里显示出来。

clip_image002

Git Extensions 的也被集成到右件菜单中。比如你可以直接提交(commit)。

clip_image003

当创建一个新项目或者打开一个现有项目,在项目浏览器用右键菜单可以快速建立一个 Git 仓库。非常方便。我已经为我所有程序项目都轻轻松松创建了 Git 仓库。

clip_image001[1]

 

这样对于习惯于用 Source Safe 和 TFS 的用户,版本控制的感觉又回来了。Git 的功能调用起来也非常顺手。

最后随便提一下这个 Git Source Control Provider 是我在开发的一个开源项目。它的主页是 http://gitscc.codeplex.com。欢迎参与和指教。

Written by yysun

一月 29, 2011 at 2:51 下午

发表在 git

Tagged with

4. 乌龟工具

leave a comment »

Windows下除了Git Extensions以外,外有个很好用的图形工具TortoiseGit。它是著名的乌龟工具组里的一员。它的同门弟兄个个大名鼎鼎。它们是TortoiseCVS,TortoiseSvn,TortoiseHg,TortoiseBzr等等。

TortoiseGit的官方主页是 http://code.google.com/p/tortoisegit。它是Windows文件管理器的外挂。它为文件管理器右键菜单增加了Git相关的功能菜单。并且可以在文件管理器里显示文件和目录在Git下的状态 (这点其实我并不喜欢。我不想让它把我文件夹里文件的图标弄得乱糟糟的)。不过对于用过它同类工具的人来说就会感觉很熟悉。

最终我还是把它加到了 Visual Studio 的 Git Source Control Provider 插件里。主要原因是它启动起来比Git Extensions快。

clip_image001

对比Git Extensions 和 TortoiseGit 的提交(commit) 命令窗口。Git Extensions 可以预览文件的改动(Diff),可以控制Git的Stage。当时正是这个Stage功能需要你一个额外的步骤,就是必须要把文件加到Stage,然后才能提交。很多情况下我发现用TortoiseGit来得快。一是它跳出来得快,再者是它帮你完成了加文件到stage,省掉了你一个步骤。

clip_image002

clip_image003

我建议读者可以尝试一下TortoiseGit。当然如果你曾经用过乌龟工具组的工具,那你会很习惯于它们一致的风格和操作方法。

Written by yysun

一月 28, 2011 at 12:32 上午

发表在 git

Tagged with

5. 管理程序的历史

leave a comment »

在程序开发的过程中,程序是一步步不断在演变中的。新的功能不断加入,错误的地方不断被修正。这每一步都包含很多有用信息。源程序管理系统 (Source Code Management, SCM) 能帮助我们保留和管理这些信息。保留和管理历史信息是软件/程序版本控制 (Version Control/Revision Control) 的前提。

当程序开发进行到一个阶段,我们通知 Git 请你记录下我这一步。这个动作称为提交 (commit, verb),提交的内容也称提交 (commit, noun)。有趣的是英文和中文里提交 (commit) 这个词都可以被用做动词和名词。中文翻译成提交我不是很满意,但是目前没有好的词。

Git 的提交往往一组文件,而不单个文件一个提交。它的好处是使得每个提交成为一个单元,比较容易管理。比如一个提交改了数个文件,如果你要取消这个提交,Git 自动处理所有文件。你无需一个个文件去挑出来。除了老式的 CVS 和Source Safe,现在比较新的源程序管理系统都是一样提交一批文件。Subversion 也用提交 (commit) 同时作为提交动作和提交的内容。而Mercurial 提交动作用 commit,提交的内容则叫变化集 (change set)。

当我们保存一些编程的步骤后,Windows下就可以用 Git Extensions 的浏览 (browse) 屏幕回顾和查看程序的历史了。

clip_image001

屏幕的上半是程序历史上的所有步骤,也称提交(commit)的列表。屏幕的下半是选中的提交的具体信息。它分成三页分别来显示提交的详细内容,提交时完整的文件结构(file tree),以及与上次提交之间的差别(diff)。用颜色来显示文件的差别(diff)很容易阅读。对应的Git命令是git log和git diff。如果用命令行可就没有图形界面这么直观了。

记录程序的历史是任何一个版本控制软件都能做的基本功。CVS,Source Safe,Subversion,TFS(Microsoft Team Foundation Server),Mercurial 无一例外。Git有什么独特之处?Git的好处在于轻便。它只需要普通的执行程序,不需要安装服务器。如果你是单机小规模程序开发,装个Source Safe很简单实用。因为单机编程轻便最重要。单机上装个 CVS,Subversion,TFS 似乎太累赘。倒是Source Safe也是很轻便的。在众多反对Source Safe的浪潮中,有时候我会挺它,因为冲着它的轻便。个人简单使用的情况问题不大。但是如果功能需求复杂了Source Safe似乎缺点大于优点,如果讲成故事大概负面的多。相反Git既轻便,而且小到单机规模,大到全世界上百人同时做Linux核心开发。选用 Git 对于各种规模的开发团队应该都没有问题。

Git的提交还有个不同寻常的功能,它可以被施加到其它分支上。比如我有两个分支(branch),这两个分支暂时无法合并(merge),而第二个分支需要第一个分支里的一个提交所做的改动。这时候我可以用Git的Cherry Pick(采草莓),从第一个分支的一堆提交中采出一个来施加到第二个分支。

这样自然就牵涉到如何给提交写注释的问题。在老式的版本管理系统中,我们常常会为一个阶段做提交。比如一个提交被注释为“加入了jQuery”。它表示到提交的那个时刻你做到什么程度了。在老式的版本管理系统里也就只能做到记录下这一步。当时Git不同,在Git里这个提交有可能可以被用到其它分支,所以通常可以注释成“加入jQuery”。查看程序历史的步骤,你就会看到一个可以重复利用的步骤。如果你的程序历史是一步步具体的做法,而不仅仅是一本哪天做到什么程度的流水帐,它就有重复利用的价值了。

不过这样打造历史是举手之劳呢,还是需要花费额外时间精力以至于不大值得去做。这个问题我还在进一步摸索中。建议读者也加以思考。

最终无论你如何组织你的程序的历史,它在Git Extensions中都将一目了然。

Written by yysun

一月 27, 2011 at 12:21 上午

发表在 git

Tagged with

6. 分支与合并

leave a comment »

分支(branch)这个概念存在已久。它的主要作用是为开发中的程序创建相对独立的环境。通常程序的不同版本在它们各自的环境,也就是分支中进行,以避免冲突和相互覆盖。所以分支是版本管理系统的核心功能。

clip_image001

CVS,SourceSafe 等老一辈版本管理系统都可以做分支。甚至不用版本管理系统,只用文件系统你也可以做分支,为每个分支做个目录即可。

要注意的是分支不是关键。合并(merge)才是关键。不能很好地合并将极大妨碍创建分支的可行性。用文件系统、用CVS,SourceSafe等做的分支不能方便地合并。因此最好不要分支才算上策。分支长期以来几乎只是个梦想。

Git 给分支和合并带来了革命性的突破。它使得分支的成本很低,还及使得分支的合并很容易。你会感觉到使用分支的束缚全部没有了。天地间突然变得开阔,心情及其舒畅。前面的故事提到 Git 的轻便是我喜欢它的一个原因。毫无束缚的分支是我喜欢 Git 第二个原因。

Git 使得分支的成本很低是得益于它的分布式(Distributed)设计。其核心思想是把仓库建立在本地硬盘上。当需要和远地的(比如服务器上的)仓库协调的时候,Git 有命令来做同步。这在以后专门有一集来介绍。

Git 的分支的操作也在本地硬盘上进行,所以Git 的分支速度很快。Git 的分支也不需要文件目录。当你从一个分支转到另外一个分支的时候,Git 会自动重建现场,你的工作目录里的文件会恢复到你离开这个分支已经的状态。例如,在一个分支里先有3个文件,然后你开了一个新的分支,并提交了几个新文件以及修改了2个文件。当切换到第一个分支的时候,你的工作目录里恢复到原先的3地个文件,其内容也是先前的内容,没有改动过。所以Git 的分支非常方便。

Git 的分支的快速和方便不但打破了以前做分支的禁忌,而且促成了质变。它使得分支不仅仅用来管理程序的版本,而且可以用来辅助尝试性程序开发,称为主题分支/专题分支(Topic Branch)。

因此用熟了 Git 的人常常会在做任何事情以前开个分支先,如果成功就合并到主分支,如果不成功则简单删了这个试验分支。比如下图里我的 GitScc 仓库。它有4个分支,VS2008 是用于 Visual Studio 2008 的发布分支(production branch),master 是用于 Visual Studio 2010 的发布分支,dev-V0.7.0 是继续开发下一版的分支。Opt-Refresh是个分支用来尝试一个新的刷新算法。这个主题分支的存在丝毫不影响新功能的开发。如果新算法成功,我可以可并到 master 分支做个更新版本。如果不成功删掉这个分支即可。

clip_image002

有时候也会忘记先开分支,直到改了一批文件后才发现我应该先开个分支。这时候不用紧张,还来得及当场现开个分支。等提交修改的内容的时候,它们会在新开的分支里出现,而不是在老的分支里。再简单不过了。

即使你已经提交了修改内容也很容易修正过来。下面就是个例子。我后悔在 master 分支里把我的网站改 ASP.NET Pages 项目了。应该开个分支来放这个变化的。这时候该怎么办?

clip_image003

亡羊补牢,现开个分支。

clip_image004

回到 master 分支 (checkout master),然后设置 master 分支的位置回到从前,并使用 Hard 选项。

clip_image005

clip_image006

现在看下图,我满意了。改 ASP.NET Pages 项目的步骤放到了它自己的分支。master 分支恢复到先前状态。

clip_image007

能这么方便归功于 Git 在本地保存着完整的历史信息。今后我还会有专门一集故事来讲如何整理历史信息。而在下一集会我先分析 Git 拥有突破性分支与合并背后的的技术背景。

Written by yysun

一月 26, 2011 at 10:10 下午

发表在 git

Tagged with

7. 三向合并

leave a comment »

上一集讲到分支不是关键。合并才是关键。Git 在分支方面能得到突破性应用。其原因就是因为它利用了所谓的三向合并 (three-way merge) 技术。

合并要解决的主要矛盾是自动处理冲突 (conflicts)。如果要把下面两个分别来自两个分支的文件合并起来,合并程序会报 2 个冲突。它们都是程序无法自动处理的冲突。需要人工介入来为每处冲突做出选择。这是传统的二向合并 (two-way merge) 面临的困境。

clip_image001

clip_image002

三向合并则是在合并两个文件的同时参照第三个文件来判定文件内容变化的情况。合并的结果将采用变化过的新的内容。比如上面例子中的 Feature 5 和 Feature 6 是有冲突的两行内容。合并工具不知道应该采用哪一行。如果有了一个参照文件,合并工具就可以知道 Feature 5 是老的过时的,Feature 6 则是新的应该被采用的内容。合并工具就能自动解决冲突,不需要人工介入而完成文件的合并。

image

clip_image004

三向合并可以大大提高自动解决冲突的成功率,使得文件合并效率大增,人工介入的需求大幅减少。Git 在合并分支的时候,先追溯每个分支的历史。找到分支的共同祖先,并把这个祖先作为基础加入合并过程,进行成功率很高三向合并的。

clip_image005

目前三向合并已经成为众多版本控制系统的必备功能。不过与和它们比较,Git 的历史追溯速度是最快的。 Linus Torvalds 被称为速度怪物 (speed freak)。可见他追求速度到了极点。他开发的这个 Git 是一定要快的,因为他常常需要合并巨大的 Linux 核心源程序库。慢了可不行。

最终的结果就是用 Git,合并分支成不再是一个噩梦,而几乎是一种享受。

Written by yysun

一月 25, 2011 at 10:23 下午

发表在 git

Tagged with