Pulpcode

捕获,搅碎,拼接,吞咽

0%

版本控制系统学习笔记(1)基本使用

最近打算写一系列博客总结版本控制系统。工作的第一年我使用的是git,工作的第二年我使用的是svn。

我现在是一个实用主义,所以我想总结一些跟实际用途有关的东西,比较偏的技巧我是不会去找的。没有必要的比较我也不会去总结。比如git是分布式的,在本地保存了所有库而svn没有。我也不会用命令行装逼,实际上当你了解了原理之后,图形界面(比如TortoiseSVN),确实很好用。

我从以下几个方面进行总结:

  1. 原理(并不是一些死扣底层的原理,而是真真实实能被我们用到的原理。)
  2. 使用方法(这要与现实相结合,我不想写一堆空旷的使用流程,而是在建立在某个情景上的使用方法。)
  3. 问题解答(对一些疑问提出解答)

什么是版本控制器?为什么要用版本控制器?

版本控制器相当于用一个数据库维护你的代码,而你编写代码的地方被称为是工作目录,你对代码的改动,都可以去提交到代码数据库中。这样你可以方便的去查找或使用早期某个版本,或者在一个分支上开发新功能,或者多人开发不同的功能,最后统一到一个代码数据库。你可以试想一下,如果没有版本控制器,单靠互相考文件,备份文件是怎样一种工作量。

这个比喻是否恰当:类似于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
2
3
git fetch origin master:tmp
git diff tmp
git merge 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
2
3
4
5
6
7
8
9
10
11
12
# 此注释将被git忽略
# 忽略所有 .a 结尾的文件
*.a
# 但是lib.a除外
!lib.a
# 忽略log目录下的所有文件
log/
# 忽略所有以 .o 或 .a 结尾的文件
*.[oa]
*.swp
*.pyc
*.

远程分支

所谓git fetch foo bar, 会将远程版本库foo的bar分支拿到你的本地仓库,然后它就放在:foo/bar中。

git clone 本质就是自动创建了本地的master分支用于跟踪远程仓库中得master分支。你本地的foo/bar,用来同步远程分支,而且不能做逆向操作。