Java服务端研发知识图谱
上QQ阅读APP看书,第一时间看更新

第3章 代码管理

本章会介绍两个优秀的版本管理工具Svn和Git。

Svn是集中式版本控制系统,版本库存放在中央服务器,必须联网才能工作。

Git是分布式版本控制系统,也就是每个研发人员从中心版本库的服务器上拉取代码后会在自己的计算机上克隆一个自己的版本库。工作的时候不需要联网,因为版本都在自己的计算机上。

3.1 Svn

Svn(Apache Subversion)是一个开放源代码的版本控制系统。文件存放在中心版本库,记录每一次文件和目录的修改。Svn允许把数据恢复到早期版本,或是检查数据修改的历史。Svn可以通过网络访问它的版本库,从而使用户在不同的计算机上进行操作,在编写代码的时候,会生成很多不同版本的代码,使用Svn可以有效管理不同版本的代码,从而把研发人员从烦琐的版本管理中解放出来。

3.1.1 Svn客户端的安装

Svn的使用需要客户端软件,本书选用TortoiseSVN[30]客户端。TortoiseSVN客户端的安装非常简单,通过如下几步即可完成软件的安装:

(1)通过搜索找到下载地址,或者直接去TortoiseSVN的官网https://tortoisesvn.net/ downloads.html进行下载。下载时选择中文TortoiseSVN的正确版本即可。在编写本书时,最新版本为LanguagePack_1.9.7.27907-x64-zh_CN.msi[31]

(2)双击执行安装。运行后程序会让你选择安装路径,设定 好文件夹后即可一步步操作直至安装完成。Svn版本信息如图3-1所示。

3.1.2 Svn基本使用

下面介绍使用Svn来管理项目。

1.获取项目文件SVN Checkout

978-7-111-61011-3-Part01-159.jpg

图3-1 Svn版本信息

可以根据Svn服务器的地址,例如svn://39.106.10.196/javadevMapSvn[32]以及用户名和密码,将项目Checkout到本地。

(1)首先在本地创建一个空的文件夹。在文件夹内执行“鼠标右键单击->SVN checkout”。如图3-2所示。

(2)在弹出的对话框中,输入Svn的服务器地址,如图3-3所示。

978-7-111-61011-3-Part01-160.jpg

图3-2 Svn快捷命令

978-7-111-61011-3-Part01-161.jpg

图3-3 配置Svn服务器地址

(3)输入地址后,点击OK,会弹出一个对话框,输入用户名和密码,记得勾选保存认证,否则每次操作都需要输入用户名和密码。

(4)进行如上操作后,可以看到Svn服务器的文档已经下载到本地,如图3-4所示。

978-7-111-61011-3-Part01-162.jpg

图3-4 拉取文件成功

2.提交本地文件到Svn服务器

(1)将要上传的文件放到Svn管理的文件夹内,然后在文件夹上执行“鼠标右键单击-> TortoiseSvn->Add…”,在弹出的对话框中勾选需要上传的文件,然后点击OK。会弹出一个确认对话框,点击OK。此时会发现文件夹或者文件上面会有一个小加号。

(2)再次在文件夹的空白处执行“鼠标右键单击->SVN Commit…”,在弹出的输入框中填写本次提交的备注,然后点击OK即可。

3.Svn更新(SVN Update)

更新本地代码至Svn服务器上最新版本,只要在需要更新的文件夹上或者在文件图标旁空白处执行“鼠标右键单击->SVN Update”即可(如果要获取指定历史版本的内容,执行“鼠标右键单击->Update to revision…”)。

4.删除Svn服务器上的文件

如果被删除的文件还未加入Svn版本库,直接删除文件即可;如果要删除的文件已加入版本库,则使用如下方法删除:

方法一,选择要删除的文件,执行“鼠标右键单击->TortoiseSVN->Delete”,然后选择待删除文件的上级目录,执行“鼠标右键单击->SVN Commit…”,并填写备注。 方法二,在计算机中直接删除该文件,然后选择被删除文件的父目录,执行“鼠标右键单击->SVN Commit…”,在变更列表中选择被删除的文件,填写备注并提交。

5.SVN还原(SVN Revert)

进入Svn文件夹中,执行“鼠标右键单击->Tortoise SVN->Update to revision…”,然后会弹出一个窗口,如图3-5所示。

例如回退到第4个版本只需要选择Revision,并在输入框中填写相应的版本号,然后点击OK即可。

6.锁定和解锁(Get lock and Release lock)

Svn具备文件锁定的能力,锁定后他人将无法修改此文件。

978-7-111-61011-3-Part01-163.jpg

图3-5 Svn还原

选中要锁定的文件,执行“鼠标右键单击->TortoiseSVN->Get lock...”进行锁定,系统会弹出锁定信息框。当文本文件锁定后,需要通过解锁,他人才能继续对文件进行修改。在被锁定的文件上执行“鼠标右键单击->TortoiseSVN->Release lock…”进行解锁。

7.重命名文件(Rename)

要修改文件名,可选中需要重命名的文件或文件夹,然后执行“鼠标右键单击->TortoiseSVN ->Rename…”,在弹出的对话框中输入新名称,点击OK按钮,并将修改文件名后的文件或文件夹通过执行“鼠标右键单击->SVN Commit…”提交到Svn服务器上。

8.获取历史文件(Show log)

Show log有显示日志的作用,主要是显示某文件或目录已经执行的操作,包含被谁修改了以及修改的时间和日期。执行“鼠标右键单击->TortoiseSVN->Show log”,会显示某路径下的所有文件版本信息。

3.1.3 Svn解决冲突

为什么会产生冲突代码呢?原因很简单,因为不同的人,同时修改了同一个文件的同一个地方,其中一个人提交了,另一个人就提交不了了。如果另一个人要提交代码,需要先进行更新,然后解决冲突后才能提交。

如果产生冲突,Svn会生成如下3个文件,用于帮助解决冲突。如图3-6所示。

■code.txt.mine是你修改后准备提交的版本,即没有提交成功的版本。

■code.txt.r1是冲突前本地的版本。

■code.txt.r2是别人赶在你之前提交的版本。

查看code.txt的内容,具体如下:

978-7-111-61011-3-Part01-164.jpg

图3-6 Svn冲突文件

978-7-111-61011-3-Part01-165.jpg

其中,<<<<<<<<.mine与=======之间的代码是你自己的,而======与>>>>>>>.r2之间的代码是别人与你冲突的部分。解决方案如下。

(1)在发生冲突的文件上执行“鼠标右键单击->TortoiseSVN->Edit conflicts”,弹出编辑对话框,如图3-7所示。

978-7-111-61011-3-Part01-166.jpg

图3-7 Svn冲突编辑对话框

注意上面一共有三个窗口,三个窗口的含义见表3-1。

3-1 冲突解决窗口含义

978-7-111-61011-3-Part01-167.jpg

对话框中有许多颜色,含义见表3-2。

3-2 冲突解决窗口颜色含义

978-7-111-61011-3-Part01-168.jpg

在红色块处单击鼠标右键,就会弹出如图3-8所示的菜单,根据菜单中的选项,进行文件的合并操作。

■use this text block:选取选中行的内容。

■use this whole file:选取选中行所在文件的全部内容。

■use text block from mine before theirs:先用自己的内容,接着再用别人的。

978-7-111-61011-3-Part01-169.jpg

图3-8 Svn解决冲突选项

■use text block from theirs before mine:先用别人的内容,接着再用自己的。

(2)根据上面的操作步骤,解决完冲突后,选择save,然后选择“Mark as resolved”,最后在Svn文件夹中执行“鼠标右键单击->SVN Commit…”即可。

3.1.4 Svn分支

在建立项目版本库时,可首先建好项目文件夹,并在其中建立trunk,branches,tags三个空的子目录。这三个目录的作用如下:

■trunk是主分支,是日常开发进行的地方。

■branches是分支。一些阶段性的发布版本,是可以继续进行开发和维护的,则放在branches目录中。或者对于项目不同的开发版本也可以放在此分支中。

■tags目录一般是只读的,这里存储阶段性的发布版本,只是作为一个里程碑的版本进行存档。

3.2 Git

Git不同于SVN,它可以在没有中央系统的情况下进行代码的提交和管理,本节详细介绍Git的用法。

3.2.1 Git客户端安装

本书选用msysGit作为Git客户端。Git客户端的安装非常简单,通过如下几步即可完成:

(1)通过搜索找到下载地址,或者直接去Git的官网https://gitforwindows.org/进行下载。下载时选择中文Git的正确版本即可。在编写本书时,最新版本为Git-2.16.2-64-bit.exe。

(2)双击执行安装。运行后程序会让你选择安装路径,设定好文件夹后即可一步步操作直至安装完成。安装完成后,在开始菜单里单击“Git Bash Here”,弹出一个类似命令行窗口的界面,就说明Git安装成功。

(3)设置全局用户名和邮箱。执行“鼠标右键单击->Git Bash Here”,在弹出的命令行中分别输入下面的命令。

$git config--global user.name"Your Name"

$git config--global user.email"Youremail@example.com"

3.2.2 Git基本使用

在使用Git之前,有必要了解一下Git的几个重要概念:Git工作区、暂存区和版本库。

■工作区(Working directory):简单地说是在计算机里能看到的目录。

■暂存区(stage):用来暂时存放工作区中修改的内容。

■版本库(Repository):工作区里有一个名为.git的隐藏目录,这个目录不算工作区,而是Git的版本库。

Git基础环境准备妥当后,需要先从远程仓库克隆项目文件。准备好远程仓库,例如git@gitee.com:hwhe/JavaDeveloperMap.git[33],这里打开“Git Bash Here”命令行,用命令git clone克隆一个本地库。

$git clone git@gitee.com:hwhe/JavaDeveloperMap.git

本节使用的远程仓库是通过Oschina创建的,Oschina给出的地址不止一个,还可以用https://gitee.com/hwhe/JavaDeveloperMap.git这样的地址。实际上,Git支持多种协议,默认使用ssh,但也可以使用https等其他协议。区别为https方式每次push都必须输入口令。

Git常用命令如下:

■git clone复制一个仓库到本地

用git clone复制一个Git仓库到本地,能够查看该项目,或者进行修改。

$git clone[url]

■git add添加文件到缓存

$git add test.java

■git status查看当前Git状态,来确定当前是否有修改

$git status

■git commit保存到本地仓库中

git commit是将修改推送到本地仓库中。使用-m选项可以设置提交注释。执行此命令之前,需要先执行git add将修改放入暂存区中。

$git commit-m '本地提交的备注'

■git push推送到远程仓库

git push命令用于将本地分支的更新,推送到远程主机。它的格式与git pull命令相仿。

$git push<远程主机名><本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull后面跟<远程分支>:<本地分支>,而git push后面跟<本地分支>:<远程分支>。

如果省略远程分支名,则表示将本地分支推送到与之存在“追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被创建。

$git push origin master

上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被创建。

■git pull同步远程分支到本地

$git pull

如果本地没有配置SSH公钥,则需要根据提示输入用户名和密码才能更新。配置SSH公钥,可以免去输入用户名和密码,具体配置方法在3.2.5节会有详细介绍。

■git reset和revert代码回滚

第一种情况,还没有push,只是在本地commit。

1)找到之前提交的git commit的id信息 $git log

2)找到想要撤销的id,执行git reset命令,完成撤销,同时将代码恢复到commit_id对应的版本。注意:hard参数的作用是使修改的代码也回滚到commit_id的版本。

$git reset--hard<commit_id>

或者

$git reset<commit_id>

不带参数hard,则仅完成commit命令的撤销,不对代码修改进行撤销,可以直接通过git commit重新提交本地修改的代码。git reset常用参数见表3-3。

3-3 git reset常用参数

978-7-111-61011-3-Part01-170.jpg

第二种情况,commit push代码已经更新到远程仓库。

对于已经把代码push到线上仓库,如果回退本地代码也想同时回退线上代码,使线上、线下代码保持一致,需要用到下面的命令:

$git revert<commit_id>

revert之后本地代码会回滚到指定的历史版本,这时再git push即可把线上的代码更新。

git reset是回退到某次提交,提交及之前的commit都会被保留,但是此次之后的修改都会被退回到暂存区;git revert是生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留。

当前使用的开发工具Eclipse默认带有Git插件,操作更加便利。例如导入项目,执行“file->import->Git”,根据提示输入对应Git信息,即可完成Git项目导入。

当要提交代码、更新项目时,只需在项目上执行“鼠标右键单击-> Team”操作对应的菜单即可,如图3-9所示。

978-7-111-61011-3-Part01-171.jpg

图3-9 Eclipse中的Git菜单

3.2.3 Git分支管理

在Git开发过程中,经常需要使用分支操作把当前的代码从开发主分支master上分离开来,在不影响主分支的情况下继续工作。分支也是Git的优秀特性之一。

■查看已有的分支

$git branch­a

■创建一个分支

$git branch<分支名>

■切换分支

$git checkout-b<分支名>

■合并分支(注意是当前的分支合并其他分支):

$git merge<其他分支名>

3.2.4 Git标签

Git可以针对某一个时间点的版本打一个标签(tag),例如当前开发了一个稳定版本,可以用“git tag…”命令打一个标签留作标记。

标签相关命令如下:

■查看所有标签

$git tag

■创建标签

$git tag<标签名>

■删除标签

$git tag-d<标签名>

■切换标签

$git checkout<标签名>

■发布标签提交到Git服务器

$git push origin<标签名>

通常的git push不会将标签对象提交到Git服务器,所以需要进行显式的操作。

3.2.5 在Git中配置SSH

Git使用https协议,每次pull、push都会提示输入密码,如果使用Git协议,然后使用SSH密钥,这样可以免去每次都输入密码的麻烦。

初次使用Git的用户要使用Git协议一般需要三个步骤:

(1)生成密钥对。

Git服务器都会选择使用SSH公钥来进行授权,每个用户必须提供一个公钥用于授权,没有的话就要生成一个。SSH公钥默认储存在账户主目录下的~/.ssh目录中。目录中有.pub后缀的文件就是公钥,另一个文件则是密钥(例如id_rsa和id_rsa.pub)。

假如没有这些文件,甚至连.ssh目录都没有,可以用ssh-keygen来创建。该程序包含在 MsysGit包里,打开“Git Bash Here”命令行执行以下命令: $ssh-keygen-t rsa-C"your_email@youremail.com"

然后,系统会提示输入密码(建议输入密码具备一定的安全性,当然不输入也是可以的),按照提示设置完成后,本地的密钥对就生成了。

(2)设置远程仓库(以码云为例)上的公钥。

进入本机当前登录用户下面的”~/.ssh”目录,执行“鼠标右键单击->Git Bash Here”,执行“cat~/.ssh/id_rsa.pub”命令,查看生成的公钥。 $cat~/.ssh/id_rsa.pub

复制生成的公钥的内容,登录码云账号,点击“头像->设置”,然后点击左边菜单的SSH公钥,复制上面的公钥内容,粘贴进“公钥value”文本域内。在公钥标题域,起一个名字。

(3)把Git的remote url修改为Git协议。

如果之前的代码已经使用Git协议,则这一步可以略过,如果之前使用的是用https协议下载的代码,可以使用如下命令查看并修改协议类型。

$git remote-v

origin https://gitee.com/hwhe/spring-mvc.git(fetch)

origin https://gitee.com/hwhe/spring-mvc.git(push)

从码云项目上复制Git协议的相应的url,执行git remote set-url来调整url。

$git remote set-url origin git@gitee.com:hwhe/JavaDeveloperMap.git。

3.2.6 用Git stash暂存代码

本节讲解git stash,它可用来暂存当前正在进行的工作,例如想pull最新代码,又不想提交当前代码。常常遇到的情况就是,为了修改一个紧急的bug,先暂存当前代码,然后迁出之前的代码,修改完bug后提交代码,最后从暂存区取出暂存的代码。

git stash使用步骤如下:

(1)保存当前修改。

git stash会把所有未提交的修改(包括暂存的和非暂存的)都保存起来,用于以后恢复当前工作内容。同时注意,git stash是本地的,不会随push命令上传到服务器上。

$git stash

$git status

通过上面的命令,可以将当前代码恢复到最近提交的状态,这样就可以先去执行其他紧急的任务。例如切换到其他分支,修改bug,修改完后,再切换到之前的分支,继续上次没修改完的内容。

(2)恢复之前临时缓存的内容。

$git stash pop

上面的命令可以将缓存堆栈中的第一个stash删除,并将对应修改应用到当前的工作目录下。也就是恢复到上一个stash命令执行之前的状态。

(3)查看所有的stash。

$git stash list

(4)移除stash,注意这里的stash的名称,可以从stash list输出里面找到。

$git stash drop<stash名称>