手把手教你如何进行 代码版本控制
请各位读者添加一下作者的微信公众号,以后有新的文章,将在微信公众号直接推送给各位,非常感谢。
0.前言
最近 S 君进入某互联网公司进行开发,可是进入公司工作的第一件事就是要将自己每天开发的成果递交给老大。
可是,这时候 S 君遇到一个问题。
“你们每天的代码要上传到仓库里,记得检查冲突。”
仓库?代码上传?这些都是什么意思呀?
抱着试试看的心态,S 君找到了我,于是也就有了今天的文章。
1.版本控制
首先在文章的开始前,先来介绍一下,什么叫做版本控制。
版本控制(Revision control)是一种软体工程技巧,籍以在开发的过程中,确保由不同人所编辑的同一档案都得到更新。
说白了,所谓的版本控制其实就是我们在日常的开发过程中,将每天、每个阶段、每个功能等要求完成之后,将我们的代码再提供给他人的一种行为。
这个行为的目的就是,让每一个人的开发过程都有据可查,最后实现多人合作开发的目的。
而版本控制的过程中,非常重要的一个问题就是,储存库(也就是仓库)的创建。
接下来我们来介绍一下,关于仓库的概念。
2.数据仓库
一般在开发的过程中,项目 leader 一般会将你们的项目仓库进行划分。
但是一般来说,不管怎么划分,都离不开以下几个内容。
首先来说一下上图中出现单词的含义。
- Master : 领导,一般是你们 leader
- Hotfix : 热修复,一般是有问题了,之后通知用户自己下载补丁
- Release :发布,就是上线了
- Develop :开发者,不用说了,就是我们
- Feature :特色,备用版本
除此之外,在开发过程中,其实跟程序息息相关的却是另外几个仓库。
这里会设计到一些公司 CTO 的想法和意见,所以每个公司都不相同,请选择查看。
一般公司内部都会有一个研发规范,而咱们需要注意的就是在研发规范中,对于仓库的使用。
PS:我居然能找到这个,当时自己都惊了。
仓库名称 | 稳定程度 | 权限 | 说明 |
---|---|---|---|
branches | 开发分支,不稳定 | 开发team有权限 | 有开发任务时,从trunk打分支到branches,分支命名以dev_为前缀,加上日期(如果trunk分支在测试且证明极度不稳定,想取稳定分支,从tags取)。开发完成时,并且开发自测完成,由研发Leader合并到主干trunk,测试从trunk发包进行测试。 |
trunk | 主干分支,趋于稳定 | 开发Leader有权限 | 最新趋于稳定版本代码存放地。开发Leader有权限从开发分支merge代码到主干,然后质量部进行测试,测试通过由运维部打上线分支到tags。研发leader要控制trunk的时序性。(也就是说尽量避免一个brances合并到trunk进行测试之后,在没有完成测试前又合并一个分支,导致测试返工。) |
tags | 上线分支,稳定 | 运维有权限 | 方便回滚和记录。以日期命名,如201* ** ** |
实际开发中,大概就是这个样子。
当然,如果你们公司使用的是 Git ,其实效果也是一样,具体的都会由你们 leader 来完成。
3.版本控制的工具
上面说了这么多的内容,我们在开发的过程中,使用到了各种仓库。
可以,我们又回到了 S 君的问题,就是,我们怎么去进行版本控制呢?
在此,我想说明的是,如果遇到一个问题,你第一个反应不应该是去询问他人,而是看看自己是否能够解决。你是自己查询资料也好,是在网络上搜索也罢,只要是你自己独立解决的问题,你的记忆会非常深刻的。
好了,回归正题。
关于代码版本控制常用的两个仓库分别是 SVN 和 Github,当然,也有很多其他的控制工具。
对于纯代码的方式,大家可以优先学习一下,而且网上教程一堆,在此就不做更多说明了。
而作者在此给大家推荐两个图形化仓库管理工具。
也就是 SourceTree 以及 Cornerstone。
关于下载地址,大家可以自行在网上搜索一下,作者在这里就不做更多说明了。
4.将你的代码上传至仓库
因为作者平常使用的都是 Git,所以这里的演示也以 Git 为准。
除此之外,今天只演示如何将一个本地的文件上传至 Git 上,如果在公司的话,请按照公司自己的标准来。
最后,在开始操作前,你需要保证自己已经有了以下内容。
- SourceTree 的客户端
- Github 的账号
如果大家之前已经使用过 SourceTree 或者已经登录过某账号了,请在 SourceTree 中删除原本账号。
之后请打开你的 Github,并登录。
之后请在右下角处,选择 New repository 去创建一个新的仓库。
点击过后会出现这个界面。
创建完毕,这时候我们就已经得到我们的仓库了。
可是,想要向仓库中添加内容,这里还只是个开始。
这时候我们找到我们的仓库的地址,复制下来。
打开我们的 SourceTree 工具。
同样点击 New Repository。
选择 Clone from URL。
选择完成后会要求你填写三个内容。
- 第一个指的是你 Github 上的那个地址链接。
- 第二个是指你需要克隆所使用的文件夹地址
- 第三个会根据第二个自动生成,当然,你也可以修改
当克隆完毕之后,我们当前这个文件夹就和 Git 上的那个文件夹相连啦。
这时候我们只需要将我们对应的文件直接拖进当前文件夹即可。
之后我们需要做的就是,回到我们的 SourceTree 中,开始提交。
当然,提交的过程中,会提示你,让你输入你 GIT 的账号和密码。
正常输入即可,当提交完毕之后,你就会发现我们的内容已经上传到 Git 上啦。
5.通过代码来完成代码的上传
5.1 初始化
通常有两种方式来进行初始化:
1)git clone是一种较为简单的初始化方式,当你已经有一个远程的git版本库时,只需要在本地克隆一份即可。 例如在终端中输入:
git clone git://github.com/someone/some_project.git some_project
上面的命令就是将远程版本库克隆到本地电脑的some_project目录下。
2)git init和git remote。这种方式稍微复杂一些。当你本地创建了一个工作目录,你可以进入这个目录,使用git init命令创建一个git版本管理库。这时候如果需要将工程放到远程服务器上,可以在远程服务器上创建一个目录,并把可访问的URL记录下来,此时就可以使用git remote add命令来增加一个远程服务器版本了。例如:
git remote add origin git://github.com/someone/another_project.git
上面的命令就会增加该URL地址且名称为origin的远程服务器。以后提交的代码只需要使用origin这个别名即可。
5.2 分支操作
-
查看本地分支:git branch
-
查看远程分支:git branch -r
-
查看所有的分支:git branch -a
-
创建本地分支:git branch name
- 注意新分支创建后不会自动切换为当前分支
-
切换分支:git checkout name
- 这里需要注意的一点就是,如果是要同步远程的分支(比如同事建立了新的分支,以保证针对某个版本的修改在该分支下),请不要在本地新建一个跟远端同名的分支,也就是说不要使用git branch name这个命令,而是直接使用git checkout name命令把远端的分支拉下来即可。以避免把新的代码合并到旧的分支里。
-
创建新分支并立即切换到新分支:git checkout -b name
-
删除分支:git branch -d name
- -d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D选项
-
合并分支:git merge name
- 将名称为name的分支与当前分支合并,是合并到当前分支,而不是合并到name分支。要注意的合并前先使用 * * git branch查看下当前所处的分支。
- 可以在后面加参数
比如我要把issue340分支合并到dev分支,可以先checkout到dev分支并使用以下命令:
git merge issue340 -n --ff
-
创建远程分支(本地分支push到远程):git push origin name
-
删除远程分支:git push origin :heads/name 或 git push origin : name。
这里需要注意的是,在开发新功能、测试或者重构部分代码时,最好是新建一条分支来操作,测试新功能OK后再合并回主分支,以避免干扰到主分支。
5.3版本操作
-
查看版本:git tag
-
创建版本:git tag name
-
删除版本:git tag -d name
5.4 撤销文件更改
git checkout有两个作用,其中一个功能是在不同的branch之间进行切换,例如git checkout another_branch就会切换到another_branch的分支上去。
另一个功能是还原代码的作用,例如git checkout app/model/user.rb就会将user.rb文件从上一个已提交的版本中更新回来,未提交的内容全部会回滚到改动前的状态。
5.5 查看git配置
git config --list该指令可以查看所有关于git的配置,用户和邮箱,远程库的URL等。
5.6 版本回滚
git版本管理的好处就在于有无限的反悔权。git reset HEAD就會回到前一版本(一個表示是前一版),並把其中的 changes 繼續留在 working tree 中。適合發現前一次 commit 有問題或是想要修改 commit log,可以修改後再重新 commit。
git reset如果加上–soft參數則會把 changes 直接加到 staging area(暂存区)。加上–hard參數表示不留 staging area 也不留 working tree(完全刪除任何修改記錄)。例如git reset --hard指令会清楚所有与最近一次commit不同的修改,也就是说放弃当前所有的更改。
如果在合并(merge)过程中发生冲突了,想放弃这次合并,也可以使用git reset --hard来取消。
git reset --hard ORIG_HEAD指令会取消最近一次成功的合并以及所有你在这次合并后所做的修改。
5.7 修改上一次提交的信息
有时候手抖,在还没有输入完提交信息的时候按了回车,可以用如下指令修改提交的信息:
git commit -m"your message" --amend
5.8 单个文件回滚
有时候为了改了一个功能,没完全测试OK就推到服务器了,发现改的功能还不如之前的好用怎么办? 有两种情况,第一种是,在你提交错误的代码到服务器后,队友还有没有提交过,可以使用该指令:
git reset --hard commit_id
其中commit_id是提交记录的代号,可以使用指令:
git log
来查看所有的提交记录,找到你需要回滚的版本即可(键盘方向键可滚动查看所有记录,鼠标目测不行)。
这里要注意的是,git会回滚到你最近一次提交的commit_id之后的版本,而不是commit_id之前的版本。在本次操作中,由于队友都没有更新,只需要找到当前提交的上一次的commit_id即可。比如今天是3月21日,你提交了错误的代码到服务器,服务端在之前3月20日有一次更新,那你找到3月20日的commit_id即可。
第二种情况是,如果你提交了错误代码后队友也有新的提交,直接版本回退会把队友新提交的代码也搞没了,这时候如果你改动的文件不多的话,可以使用单个文件回滚的方式: 1)执行git log test.h查看该文件的提交记录,找到需要回滚的commit版本,复制版本号。 2)执行git reset “commit版本号” test.h 3)继续执行git checkout test.h,文件回滚成功。
需要注意的是,如果文件在比较深的目录下,上述操作室需要输入目录结构的,比如git log aaa/bbb/test.h。
5.9 其他
-
提交代码的通常步骤git status查看当前状态,有改动则使用git add.把所有改动添加到本地仓库or暂存区?然后git commit -m"your commit message"后,先it pull拉下服务器的最新代码,确认没有问题后可以git push提交代码。
-
git pull之后,或者进入其他界面,都可使用:wq退回到git的操作界面
-
如果在git pull或者git push时,提示没有设置pull或者push的默认分支,按照提示的指令设置默认分支即可。
再次强调,在开发新功能、测试或者重构部分代码时,最好是新建一条分支来操作!
6.后记
前前后后花了 6 个多小时,总算是写完了。
希望能够帮到你们吧。
看完记得点个赞。
最后,本文由 李鹏 手打完成,请勿随意转载。
作者保留法律追究权利。