git 简介
git 是目前最流行的分布式版本控制系统,大家都知道,它的诞生是由于 Linux 系统之父林纳斯痛恨集中式的版本控制系统 CVS 和 SVN,花了两周的时间写出来的。分布式系统最突出的特点是它的去中心化。git 不像 CVS 或 SVN 那样需要有一台存放版本库的中央服务器,而是在每个用户电脑上都有一个完整的版本库,可以在自己的电脑上进行代码的修改与提交,不需要联网,因此速度很快,就算一台电脑出了问题,也不影响其他电脑的工作,备份和恢复都十分方便。这也是 git 一经问世,就火遍全球的原因。
git 的教程遍地都是,而且写的都还不错,比如廖雪峰的 Git 教程, 在这里我只是介绍下工作当中常用到的 git 命令,包括分支管理,冲突解决,版本回退。这也是刚开始接触 git 时比较令人困惑的地方。
git 之分支管理
在一个项目的开发过程中,一般都会有两个分支——master 分支和 develop 分支。生产环境跑的代码位于 master 分支,测试环境的位于 develop 分支。当需要开发一个新功能时,需要执行下面命令,从 master 创建一个新分支,比方说是 issue-1:
1 | $ git checkout -b issue-1 |
此时你已经切换到了这个新分支,现在你就可以进行新功能的开发了。比如你现在开发的文件是 GOT.txt,那么过程中需要频繁使用下面两个命令:
1 | $ git add GOT.txt # 将工作区的修改提交至暂存区 |
为了“偷懒”,可以合成一个命令:
1 | $ git commit -am 'add GOT.txt' |
5 分钟后,你的新功能已经开发完成了,但是还没有进行测试,接下来需要合并至 develop 分支并推至远程仓库进行测试:
1 | $ git checkout develop |
如果测试有问题,就重新切回 issue-1 分支进行修改,并重复以上步骤。5 分钟后,bug 全都被搞定,接下来就可以将新开发的代码合并至 master 分支并推送至远程仓库:
1 | $ git checkout master |
如果你没有 master 分支的 merge 权限,就需要先将自己的分支推送至远程仓库:
1 | $ git push origin issue-1 # 若没有则会创建 |
然后在 gitlab 上提交 merge request 申请,让有权限的人帮忙合并至 master 分支。
最后,需要删除你的本地分支和远程分支(如果有的话):
1 | $ git branch -d issue-1 # 删除本地分支,如果未 merge,则需要使用 '-D' 来删除 |
git 之冲突解决
由于一个项目很可能是多个人在开发,故在使用 git merge 的过程中,难免会出现冲突,手动解决冲突的确是一件让人感到头冷的事,因为很可能误删或者少删了某些代码,而出现意想不到的问题。为了不那么头冷,我们可以通过命令来实现。
假设现在你正在将刚刚开发的新分支 issue-1 合并至 develop 分支,工作环境处于 develop 分支,如下图所示:
1 | HEAD |
如果未发生冲突,执行 git merge issue-1 之后的变化如下:
1 | HEAD |
如果 B 和 C 同时修改了 A 的同一行代码,就会引发一个冲突。假设 GOT.txt 文件在版本 A、B 和 C 中的内容分别是 Jon Snow、Tyrion Lannister 和 Arya Stark,执行 git merge issue-1 会失败, GOT.txt 会变成下面的样子:
1 | <<<<<<< HEAD |
可以看出,<<<<<<<、======= 和 >>>>>>> 标记出了冲突的位置,<<<<<<< 和 ======= 中间的部分称为 ours,======= 和 >>>>>>> 中间的部分称为 theirs,如果仅保留单方的修改,则可以通过下面的命令来实现而不需要在文本中进行编辑:
1 | $ git checkout --ours GOT.txt # => Arya Stark |
然后执行 git commit -am 'fix conflicts' 提交为版本 D。如果项目中很多文件发生了冲突,则可以使用 git diff <filename> 来查看单个文件的冲突内容,并使用上述命令依次解决。
git 之版本回退
试想你开发上线的新功能,因测试不够周全而出现了问题,而且问题目前还无法定位,老板让你立刻版本回退,你心想:“坏了,自己从没遇到过这种版本回退的情况,要怎么办呢?”,为了让你不在原地一脸懵逼,可以继续往下看。
首先,回退操作过程中为了保险起见,创建一个当前 master 分支的备份分支 master_backup:
1 | $ git branch master_backup |
如果想要简单粗暴一些,只需执行以下命令即可完成回退操作:
1 | $ git reset --hard HEAD^ # 回退至上一版本 |
在 git 中, HEAD 指当前版本,HEAD^ 指上一个版本,上上个版本则是 HEAD^^,如果往上 100 个版本呢? 可以写成 HEAD~100。 git push -f 是令人嗤之以鼻的操作,因为它将远程仓库的提交记录完全覆盖为你本地的记录,这就有可能导致别人辛辛苦苦开发的代码都被你给搞没了!曾因为 git push -f 这个命令发生过命案你敢信!所以使用这个命令的时候一定要谨慎谨慎再谨慎!
还有一种情况,就是你并没有权限使用 git push -f 这个命令。那么这种情况该如何回退呢?
可以先将远程的 master 分支删除,然后将本地回退后的 master 分支推送至远程:
1 | $ git reset --hard HEAD^ |
当然,这种情况也一定不要忘记备份哦!