关注微信号:javalearns 随时随地学Java
或扫一扫
随时随地学Java
本文集中讨论版本控制如何工作。我将从宏观的角度开始,结尾将关注于一个具体的Git例子,Git是一个最近比较流行的版本控制系统。你或许已经知道这个版本控制主要用来追踪和记载一个或者多个文件的历史记录。然而,也许你还没用过版本控制,也就不熟悉它的它提供的诸多好处,还有不确定每个系统的细微差别。
宏观角度看软件版本控制
版本控制的核心是这样一个简单的概念,即对一个或者多个文件的追踪过程,随着这些文件演变成一个或多个产品的过程。特别是版本控制追踪什么变化,是什么改变了它,为什么会这样。版本控制系统提供了一个有益的说明,这写说明在传统的文件管理中是找不到的。
需要注意的是版本控制使用不仅是局限于程序员。版本控制可以被任何人用来维护文件目录,因此即便你不是程序也可以继续阅读此文。版本控制系统有很多选项,对于本文,我将讨论Git。需要牢记的是,不管你最终选择什么样的版本,都只有一个相同的目的,就是帮助你组织和保护你的源代码和文件。
版本控制的概念
重要的是掌握基础概念,特别是在你和你的团队集中某一具体版本控制系统之前。这里有三个具体的概念,我将在本文中专注于此。
- 源代码支持
- 历史视角(版本)和评价(说明)
- 回滚
在一些版本控制系统中,恢复某个文件是可能的;在多数版本控制系统中,整个目录的恢复也是可能的。得到一杯牛奶和你最好的饼干,因为我在这里要告诉你,犹豫是否改动源代码的日子已一去不复返。举个例子,在Drupal社区存在模块的沙盒版本,模块不过是产品代码的一个分支版本。
倘若你在一个开发团队工作中弱化版本控制的使用,在你重写工作中的产品代码,不可避免地造成一些收益和宝贵时间的损失。 许多程序员会得到丰厚的报酬,那在商业环境中损失是不可以接受的。
Git利用一个数据库去追踪和报道变化。举个例子,假设此刻,我是一个是一个出色的Druper程序开发人员,为起居写了软件模块。我认为我需要重写我的spectacular模块中的一个功能。我致力于将源代码返回至存储中,这个新的致力版本存在于Git的一个简单类似数据库的系统中。我不再去担心追踪它们的变化,相反Git会为我做这些工作。因为标注在致力过程中是必须的,我能追溯我的标注,如果我的模块是spectacular,为什么我需要重写它。我确信你熟悉软件版本。比如Drupal发布都会有其版本号。在我写这篇文章时,Drupal7.24核心版本已经发布了。如果你正在使用版本控制你或许会指Drupal7.24作为一个标签或者一个标记分支。标签或者标记具有里程碑式的意义。
在我们深入之前,你必须熟悉几个重要的术语。这些术语用一套规范的方式去定义,你能将这些知识用于如果不是全部至少是多数的版本控制系统。
- 存储-存储是个普遍术语。版本控制系统管理一个存储,在Git中存储实际上就是一个数据库,在那里文本和历史都得到维护和保存。
- 工作集-工作集包括文件和文件夹。通常你会看到一个存储包含多个工作集,这些工作集组织在通常称作项目中。当你编辑一个工作集时,你顺带地就会升级存储。版本控制最重要的事情就是,当你升级你的存储时,你自动地创建了一个源代码支持,不仅是保存。关于工作集有一点需要记住的是,文件包含潜在的变化已不在存储中了。
- 添加和检入-正如你猜测的那样,添加是一个概念,即你添加新的文件或者提交和查找存在的文件。
- 返回/回滚-如果你需要返回到早前的文件版本,你将会返回或者回滚在存储中任何版本的工作集。
- 检出-如果你正在检出存储中的一个文件,通常你会将主干带入你当地的工作集中。在一些案例中,检出一个文件的活动或锁住这个文件,以防其他的开发者使用。
- 分布存储系统-通常假设你在一个分布存储系统中工作,那真个存储都在你本地的开发框内。Git就是一种分布版本控制系统。如果你需要从存储中查询数据,你可以拉出数据。如果你需要添加或者检查文本到存储中,你可以推进数据。强烈建议,即使不需要用到SSH去和存储交互如果它在一个远程服务其中。
- 标签和标记-此概念用来说明一个具体存储的状态。你或许标签或者标记了一个你的Drupal模块版本,你认为可以稳定发布的。
- 分支和分叉-这是一个常见的概念,即创建一个完整的存储拷贝。通常,你会听到一个沙盒代码的术语,它的意思是一个开发者已经分支或者分叉了一个项目存储。
- 合并-如果你分支或者分叉了一个存储,那么你将不可避免地想要把你的源代码推送到存储的主干或者主要分支中。推送分支或者分叉代码返回主干的过程,就是指调用合并。
集中 VS. 分布版本控制系统
在本文中我将深入的讨论Git,作为一种分布版本控制系统。注意我不会深入探讨集中版本控制系统的细节,集中版本控制系统不在本文讨论范围之内。在外壳,集中版本控制系统常用于大型软件开发,你通常会碰到的两个版本是Microsoft Team Foundation Server (TFS)和 Subversion.。我建议你花时间去学习集中版本控制系统,尽管,需要确定它们是否是你的开发坏境所需要的。
分布版本控制工作与集中版本控制比较而言是不同的。特别是,当你在本地开发机器上初始化存储。在你本地的开发存储机器上,你有一个工作集,你在存储中添加和升级了文件。因为我会讲到Git,你应该知道,可以用远端存储源代码。通常远端存储会用到GitHub。不去涉及太多细节,GitHub是一个云服务,借助于此你可以将本地存储放在云端。
Git的存储行为
Git是一个分布版本控制系统,它是一个开放代码项目,这个项目会用到GNU通用公共许可证版本2,因此它是免费的。你可以下载Git http://git-scm.com。
下载Git并且在安装过程中,在多数情况下,安装时的诸多默认选项很多。然而,出于本文的目的,我将选择Git Bash作为仅有的壳类型,因为我感觉Linux命令行shell很舒服。同样,我也选择“Checkout Windows-style and commit Unix-style line endings”。在这个环境下,我可以使用存储在苹果或者Linux操作系统开发环境中。
安装之后,你可以验证Git安装是否成功,即发布来自Git Bash shell 的命令git–version。Git Bash shell 在安装过程有提供 git –version。
如果你想看版本号以便git正确安装,在开始版本控制时,你需要创建整个存储或者一部分存储,为你正在工作的项目。借用Git版本控制系统,你创建自己的存储在你的本地开发机器上。记住,重要的是Git存储需保存在你文件的相同目录中。
为此,本文我将在dev目录下进行工作。
来自dev目录,我将执行git init命令去初始化一个空的存储:
1
|
git init
|
接下来,我会验证这个空的存储,借用git status 命令:
1
|
git status
|
通常你会看到一条语句,nothing to commit 特别在目录为空时。
你应该意识到一个隐藏的目录称之为.git,在那里保存了所有存储元数据。如果你想回到Git存储和所有完好的编辑历史,确保包括这个.git文件夹。
在此,你或许想提交文件给你的存储,但在你做任何事情之前,你必须设置两个Git配置项。记住版本控制系统倾向于显示说明。有鉴于此,我必须确保所有的源代码编辑标记有我的名字和邮件。我设置两个配置项:
1
2
|
git config user.name “web3”
git config user.email <a href=
"mailto:example@warrenbullock.me"
>example@warrenbullock.me<
/a
>
|
提交文件
现在我可以提交一些文件到我的存储中。有鉴于此,我将通过Drupal7 网络端存储来说明版本控制。首先,我得告诉Git去跟踪一个称为style.css的类型表单。
1
|
git add style.css
|
如果询问我的Git工作集的状态,它会告诉我文件在提交时变化,紧随新文件名之后。因为我知道存在一个叫style.css文件,它需要提交,我发布git commit命令:
1
|
git commit
|
在上面的例子中我没有添加任何参数给commit命令。当你在用命令行工具,特别是—m选项,你只能添加一个简短的信息版本,这条信息是条很重注释。如果你不选—m 选项,命令行工具会给你打开一个默认的文本编辑器,这样你就可以加入一个随之而来长的注释。我的默认文本编辑器是VIM。在我打入信息后,我按下逃逸键,然后我打入:wq to save and quit。借助于保存这个注释并且推出VIM,我边得知信息的状态,1文件改变,1插入(+)。还有许多方法添加信息给一个文件提交。我能提供–a –m作为提交命令的一部分。–a简单地意味提交所有文件在一个工作的目录中。–m是提供一条信息,文件在提交之前发生了什么变化。
尽管我已经提交了sytle.css文件到存储中,如果我发布git log命令,我会看到我原始的检查:(译者注添加)
1
|
git log
|
默认的git log输出肯定让人困惑,更优的选择是git log –online – all。这个log,命令的变体将会仅仅展示当前存储中的changeset IDs 和文件注释。
有机会你可以比较文件的两个不同版本。这个时常发生,因为常常存在冲突,Git不能确定那个文件版本需要保留。如果你想比较不同的style.css版本,我会用到git diff命令:
1
|
git
diff
style.css
|
返回到先前的某一个版本
不可避免地你打算返回或者回滚到某处正在工作的源代码。这个过程很简单当你用版本控制系统,特别是Git。关于这个,我已经检查过我的style.css文件。我知道我我在存储有一个可以依靠的版本。当我意识到需要返回我的style.css文件是,我简单地在主干存储中检出它。我做了明确地编辑并且提交了变化。
很少的一部分选项,将代码检出加入一个工作集中,我能回滚多数当前的提交或者我能回归到一个特定的修订版本。如果我想回滚到许多当前的提交,我可以发布git checkout HEAD style.css命名:
1
|
git checkout HEAD style.css
|
或者我可以回滚到任何特定的修订版本,借助于checkout命令 ,伴随存储中问文件guid(译者注:数字标识符)。当我发布git log –oneline—all命令 所有的与文件名相关的guid都会展示出来,因此我可以回滚到一个特定修订版本,比如此例中的98c12
1
|
git checkout 98c12 sytle.css
|
创建一个标签和标记
在此,我仅有一个标识文件,借助uchangeset标识符和guid比如98c12.然而通常的例子,你需要鉴别真个存储状态,在开发周期中一个特殊的位置。一个软件开发周期的例子或许是一个产品的发布。版本控制系统允许你提供人类可读的名字给整个存储,在Drupal7的例子中,它或许是-7.24。
Tagging and labeling often times是可互换术语取决于你所用的版本控制系统。因为我们正在用Git,我将要所指的过程作为标签(tagging)。在Git创建一个tag,我能发布命令git tag:
1
|
git tag drupal-7.24
|
如果我想确切地了解tag中存在什么,我可以发布命令:
1
|
git show drupal-7.24
|
正如你可以检出一个特定的文件到你的工作集,你也可以检出一个特定的tag。我发布git checkout drupal-7.24:
1
|
git Checkout drupal-7.24
|
标签是一个超级强有力的概念特别是和分支和合并联合在一起时。让我们假设你需要些一个特定代码为你的产品版本2.0.一种常见的策略是检出标签版本(1.0)。因为你已分支版本2.0,你可以编辑写代码。稍后,当你自信版本2.0已经可以发布了,你或许会将版本1.0和2.0返回到你的干或者主要分支中。记住,这是仅有的单一策略。你或许决定从不分支或者分叉代码。这全取决于你。
分支和合并
或许多数用过的和有用的在版本控制系统的所有特征是分支。在Git中,分支和合并是非常容易和相当轻量级的。我可以创建一个新的分支,即发布git branch命令 紧随其后的是新分支的名称:
1
|
git branch drupal-8.0.0
|
如果我发布命令git branch 没有任何选项,我能看到一个列表的当前分支,附在我当前筛选的分支后。在Git中,你当前筛选的分支标注在星号和绿色的文本之间。
因为我确认过我在当前的主干分支中,我会发布checkout命令在新的分支有效标记为活跃状态:
1
|
git checkout drupal-8.0.0
|
正如你所想象的那样,这是一个为实验性代码的完美沙盒。你可以自由地做任何你想做的,不需要考虑产品存储。分支相连是一个逆过程,称之为合并。合并允许你在分支中所做的改变,添加它们到重要的主干或者其它分支中。
合并分支借用Git是很简单的。记住,检查文件到你私人的分支常婵是指向前整合。它的逆过程称之为逆向整合,包括你检查文件回到主要分支或者主干。唯一你可以决定是合适逆向或者向前整合代码。尽管我猜它取决于多少开发人员参与你的产品开发,同时,取决于你私有和主要分支的有多活跃。
如果我想合并我的私有分支到主要分支或者主干,我会发布git merge命令,紧随其后的是我想合并的分支名:
1
|
git merge drupal-8.0.0
|
正如我早前陈述的那样分支和合并是粉盒版本控制系统两个重要的特征。用分支任何时候都可以确保主要分支和主干或者其他分支保持完整。
检验壳整合(再次关注Git)
在许多例子中,命令行接口针对的每个版本控制系统是你将会用到的,然而,许多版本控制系统同样也支持挂在操作系统shell,通过shell整合概念。简单地说,借用shell整合,你可以通过你的操作系统的窗口层和文件取得交互。在微软windows系统中,它会是windows Explorer,在Mac OS X中它是Macintosh Finder,在Linux分布中,它是X windows system。借用shell整合,你可以添加文件,检入文件,检出文件,返回,当前你所用的全部来自于shell的内部,通常shell整合选项出现在一个目录菜单中。
多数时候,版本控制系统也会提供可视的状态显示器,显示文件标识在查询状态。通常shell整合是一个可选的组建,在安装版本控制系统中。
图形用户界面工具(GUI)
除了命令行和shell整合,这里还有另外一种流行的方法去访问,一个版本控制系统的存储。这个方法通常指的是GUI tool。
多数但非所有的GUI tool包括功能, 允许你做一些与命令行确实相同的操作。比如添加,检入和检出,回滚、分支和合并。或许GUI tool工具最大的优势就是它能够可视化的检查存储并且在一个原始文件浏览器重打开文件。
Git支持许多GUI tool。我推荐你看GUI 客户页,在Git项目网址http://git-scm.com/downloads/guis。有许多可选项可供选择。我个人喜欢Windows的GitHub http://windows.github.com/,因为它而已很好的早windows平台上运行,并且可以直接整合GitHub云服务。
GUI 工具主要在于个人爱好,它们可以帮助你和你的团队工作神速。如果你不喜欢用命令行,GUI 工具提供了一个很棒的选择。
选择版本控制
此文中我已讨论了一种特定的版本控制系统。尽管Git是一种很棒的选择,但它可能不适合你的开发环境。有很多版本控制系统可以选择。它们中比较流行的一些包括:Subversion,Microsoft’s Team Foundation Server,还有Mercurial。你或许会问,你怎么知道那个版本控制系统适合你的开发环境呢?牢记这些考虑。
- 如果你在一个大型的团队环境中工作,所有的开发人员一起工作在一个相同的办公室,那么你或许想试一试集中版本控制系统。Subversion、TFS或许很适合。
- 如果你开始组建你自己的团队,那我强烈推荐你使用Git或者Mercurial。
- Git会挂入很多集成开发环境,并且提供GitHub云服务。正如你或许知道的那样,GitHub是一个免费的开放项目。如果你需要保存商业代码,它依旧是可以承受的。Git能搞定它,对你而言很容易用Git存储在你本地设备上,接着推进你的变化周期性地Git 枢纽服务器的云端服务器中。
- 如果你的软件开发团队分在世界的各个角落里,Git和Mercurial将是一个很棒的选择,因为你可以输出和输入以及发送变化,借用email而无需建立一个服务器基础设施去保存一个存储。
如果你需要证明Git在现实世界中多么有效,或许你感兴趣的例子是知道,在你最喜爱的Linux分布中的kernel保存在Git存储中,它的运作无需比如说,这个开发团队很大分散在世界的各个角落里。
选择一个你觉得运行不错的版本控制系统。如果你仅仅是开始,你在选择是有很多回旋余地,那我建议你使用Git。衷心希望你能采用一种你想要的版本控制系统。
关注微信号:javalearns 随时随地学Java
或扫一扫
随时随地学Java