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^ |
当然,这种情况也一定不要忘记备份哦!