最近打算写一系列博客总结版本控制系统。工作的第一年我使用的是git,工作的第二年我使用的是svn。
我现在是一个实用主义,所以我想总结一些跟实际用途有关的东西,比较偏的技巧我是不会去找的。没有必要的比较我也不会去总结。比如git是分布式的,在本地保存了所有库而svn没有。我也不会用命令行装逼,实际上当你了解了原理之后,图形界面(比如TortoiseSVN),确实很好用。
我从以下几个方面进行总结:
- 原理(并不是一些死扣底层的原理,而是真真实实能被我们用到的原理。)
- 使用方法(这要与现实相结合,我不想写一堆空旷的使用流程,而是在建立在某个情景上的使用方法。)
- 问题解答(对一些疑问提出解答)
什么是版本控制器?为什么要用版本控制器?
版本控制器相当于用一个数据库维护你的代码,而你编写代码的地方被称为是工作目录,你对代码的改动,都可以去提交到代码数据库中。这样你可以方便的去查找或使用早期某个版本,或者在一个分支上开发新功能,或者多人开发不同的功能,最后统一到一个代码数据库。你可以试想一下,如果没有版本控制器,单靠互相考文件,备份文件是怎样一种工作量。
这个比喻是否恰当:类似于mvc,你的工作目录相当于view,git相当于control,版本库相当于model。
git基本命令
git add xxx
这个命令比较多用,可以将新的文件添加给git,也可以将修改过的文件提交给git,让其选择下次要commit的文件。还可以在解决冲突后,将其add,表示冲突已经解决。
git clone
将某个地方的版本库,克隆到一个新的路径
git commit
将新的代码做一次提交
git fetch
获取某个版本库的代码到本地
git init
用git初始化一个文件夹,使其能够用git管理
git merge
合并版本(一般我们会先将代码fetch下来,然后在进行merge)
git mv
不要直接移动git管理的文件,而是使用git mv
进行操作。
git pull
相当于git fetch
+ git merge
git push
将本地最新一次commit
的代码,push
到远程版本库中。
git rm
对于打算不再使用git进行跟踪的文件,也要使用git rm
进行操作
git status
查看当前git的状态
svn基本使用总结
服务端: VisualSVN Server
客户端: TortoiseSVN
在window上开发,我不会使用命令行,因为不好用。
类似于git,我们可以在服务器先建立版本库,然后将其CheckOut
下来,在其文件夹下写代码管理。也可以将本地的代码用svn管理(Import),然后推到服务器上的版本库。
TortoiseSVN会将已修改的文件进行标记。最常使用的两个操作是Updater
(将服务器端的代码获取到本地),Commit
(将本地的代码推送到服务器)
因为使用TortoiseSVN,所以很多细节的东西,算是它帮忙做了,要比命令行好用很多。
问题?什么时候会有冲突?
一开始我对此概念总是混淆。不明白什么时候会产生冲突。
首先,如果是你一个人玩,那么你怎么修改,怎么commit,怎么push,都不会产生冲突的。
冲突一般在如下情景下发生:
你在向服务器上传自己的代码时,发现在你上次获取服务器最新代码到这次提交,中途有其他人进行了提交。所以会先提示你将服务器最新版本的代码获取到本地。
之后,如果你准备要提交的当前修改与服务器已提交修改在同一地方,才会产生冲突。那么这时就要解决冲突,才能将解决后的代码提交至服务器。
关于分支
git clone默认会把远程仓库整个给clone下来 ,但只会在本地默认创建一个master分支。
如果远程还有其他的分支,此时用git branch -a查看所有分支。
克隆某一分支:git clone -b <branch> <remote_repo>
特殊分支
这些特殊分支都是指针?我的理解。
HEAD: 它是一个指向你正在工作中的本地分支的指针(译注:将 HEAD 想象为当前分支的别名。)
FETCH_HEAD: 某个branch在服务器上的最新状态’.
获取远程分支
1 | git fetch origin master:tmp |
merge某个指定文件
git checkout [branch] -- [file name]
关于merge
merge到底在做一个怎样的操作?先fetch在merge和直接pull有什么不同?
merge只有在你我(两个branch)修改同一文件的同一个地方的时候,才会有冲突。
而且对于文件而言,每一次在这个branch中修改commit, 就会曾加一个版本号。合并也是基于这个版本号。
所以如果冲突之后,我解决冲突合并了,如果你不改,我怎么合并都不会产生diff冲突,因为冲突是建立在你我都修改的基础上。
如果你修改,但是我删除一个文件,那么合并也会有冲突:
CONFLICT (modify/delete)
如果我删除了一个文件,但是你修改了它,那么合并也会产生冲突:
CONFLICT (modify/delete):
所以为了防止有一些奇奇怪怪的代码被加进来,你最好使用diff命令先看一下,然后再merge之后在检查一下。
关于diff
当前目录与已暂存内容的差异: git diff
已暂存与上次commit的差异: git diff --cached
如果你想单纯的比较两个分支内容有什么不同。(无增量思想)git diff master dev
比较两个分支间的差异(注意两个点): git diff master..test
如果你想查看它们以及它们的共有父分支有什么不同,使用: git diff ...(branch)
关于忽略
1 | # 此注释将被git忽略 |
远程分支
所谓git fetch foo bar
, 会将远程版本库foo的bar分支拿到你的本地仓库,然后它就放在:foo/bar中。
git clone 本质就是自动创建了本地的master分支用于跟踪远程仓库中得master分支。你本地的foo/bar,用来同步远程分支,而且不能做逆向操作。