您的位置:首页 > 其它

Git基本操作 vs SVN

basycia 2016-07-12 15:10 120 查看
 FROM http://www.cnblogs.com/guanghuiqq/archive/2012/08/27/2658752.html

             http://www.open-open.com/lib/view/open1332904495999.html

             http://www.cnblogs.com/xh831213/archive/2008/05/14/1196786.html

版本控制原因:

1.1         小明负责的模块就要完成了,就在即将Release之前的一瞬间,电脑突然蓝屏,硬盘光荣牺牲!几个月来的努力付之东流——需求之一:备份

1.2         这个项目中需要一个很复杂的功能,老王摸索了一个星期终于有眉目了,可是这被改得面目全非的代码已经回不到从前了。什么地方能买到哆啦A梦的时光机啊?需求之二:代码还原

1.3         小刚和小强先后从文件服务器上下载了同一个文件:Analysis.java。小刚在Analysis.java文件中的第30行声明了一个方法,叫count(),先保存到了文件服务器上;小强在Analysis.java文件中的第50行声明了一个方法,叫sum(),也随后保存到了文件服务器上,于是,count()方法就只存在于小刚的记忆中了——需求之三:协同修改

1.4         老许是一位项目经理,我会告诉你他把每一个版本都保存一份吗?我会告诉你这些工程里其实有很多文件都是重复的吗?我会告诉你老许为这事删了很多电影吗?——需求之四:多版本项目文件管理

1.5         老王是另一位项目经理,每次因为项目进度挨骂之后,他都不知道该扣哪个程序员的工资!就拿这次来说吧,有个该死的Bug调试了30多个小时才知道是因为相关属性没有在应用初始化时赋值!可是二胖、王东、刘流和正经牛都不承认是自己干的!——需求之五:追溯问题代码的编写人和编写时间

1.6         小温这两天幸福的如同掉进了蜜罐里,因为他成功的得到了前台MM丽丽的芳心,可他郁闷的是这几天总是收到QA小组的邮件,要求他修正程序中存在的Bug,可他自己本地电脑上是没有这些Bug的,“难道我的代码被哪个孙子给改了?”。是的,小温没来的时候,丽丽是QA小组小郑的女朋友啊!——需求之六:权限控制

(from 不知哪里)

SVN:版本控制工具

1.1         SVN基本操作

检出(checkout):将一个服务器端创建好的项目整个下载到本地,这是到项目组后参与开发的第一步,只需执行一次。

更新(update):将本地文件更新为服务器端的最新版本,通常为每天上班时或修改公共文件之前执行一次。

提交(commit):将本地修改提交到服务器端。通常每天下班前或每实现一个功能、完成一个模块时执行一次。

Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体验到原来一个版 本控制工具可以对开发产生如此之多的影响,文章分为两部分,第一部分介绍Git的一些常用命令,其中穿插介绍Git的基本概念和原理,第二篇重点介绍 Git的使用技巧,最后会在Git Hub上创建一个开源项目开启你的Git实战之旅


1、Git是什么

        Git在Wikipedia上的定义:它是一个免费的、分布式的版本控制工具,或是一个强调了速度快的源代码管理工具。Git最初被Linus Torvalds开发出来用于管理Linux内核的开发。每一个Git的工作目录都是一个完全独立的代码库,并拥有完整的历史记录和版本追踪能力,不依赖于网络和中心服务器。

        Git的出现减轻了许多开发者和开源项目对于管理分支代码的压力,由于对分支的良好控制,更鼓励开发者对自己感兴趣的项目做出贡献。其实许多开源项目 包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已经过渡到使用Git作为自己的版本控制工具。对于我们这些喜欢写代码的开发者嘛,有两点最大的好处,我们可以在任何地点(在上班的地铁 上)提交自己的代码和查看代码版本;我们可以开许许多多个分支来实践我们的想法,而合并这些分支的开销几乎可以忽略不计。


2、Git 1+1

        现在进入本篇文章真正的主题,介绍一下Git的基本命令和操作,会从Git的版本库的初始化,基本操作和独有的常用命令三部分着手,让大家能够开始使用Git。

        Git通常有两种方式来进行初始化:

        git clone: 这是较为简单的一种初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份,例如'git clone git://github.com/someone/some_project.git some_project'命令就是将'git://github.com/someone/some_project.git'这个URL地址的远程版 本库完全克隆到本地some_project目录下面

        git init和git remote:这种方式稍微复杂一些,当你本地创建了一个工作目录,你可以进入这个目录,使用'git init'命令进行初始化,Git以后就会对该目录下的文件进行版本控制,这时候如果你需要将它放到远程服务器上,可以在远程服务器上创建一个目录,并把 可访问的URL记录下来,此时你就可以利用'git remote add'命令来增加一个远程服务器端,例如'git remote add origin git://github.com/someone/another_project.git'这条命令就会增加URL地址为'git:
//github.com/someone/another_project.git',名称为origin的远程服务器,以后提交代码的时候只需要使用 origin别名即可


3、Git的基本命令    

     现在我们有了本地和远程的版本库,让我们来试着用用Git的基本命令吧:

        git pull:从其他的版本库(既可以是远程的也可以是本地的)将代码更新到本地,例如:'git
pull origin master'就是将origin这个版本库的代码更新到本地的master主枝,该功能类似于SVN的update

        git add:是将当前更改或者新增的文件加入到Git的索引中,加入到Git的索引中就表示记入了版本历史中,这也是提交之前所需要执行的一步,例如'git
add app/model/user.rb'就会增加app/model/user.rb文件到Git的索引中

        git rm:从当前的工作空间中和索引中删除文件,例如'git
rm app/model/user.rb'

        git commit:提交当前工作空间的修改内容,类似于SVN的commit命令,例如'git
commit -m "story #3, add user model"',提交的时候必须用-m来输入一条提交信息

        git push:将本地commit的代码更新到远程版本库中,例如'git
push origin'就会将本地的代码更新到名为orgin的远程版本库中

        git log:查看历史日志

        git revert:还原一个版本的修改,必须提供一个具体的Git版本号,例如'git
revert bbaf6fb5060b4875b18ff9ff637ce118256d6f20',Git的版本号都是生成的一个哈希值、

        上面的命令几乎都是每个版本控制工具所公有的,下面就开始尝试一下Git独有的一些命令:


4、Git独有的一些命令

       git branch:对分支的增、删、查等操作,例如'git branch new_branch'会从当前的工作版本创建一个叫做new_branch的新分支,'git branch -D new_branch'就会强制删除叫做new_branch的分支,'git branch'就会列出本地所有的分支

        git checkout:Git的checkout有两个作用,其一是在不同的branch之间进行切换,例如 'git checkout new_branch'就会切换到new_branch的分支上去;另一个功能是还原代码的作用,例如'git checkout app/model/user.rb'就会将user.rb文件从上一个已提交的版本中更新回来,未提交的内容全部会回滚

        git rebase:用下面两幅图解释会比较清楚一些,rebase命令执行后,实际上是将分支点从C移到了G,这样分支也就具有了从C到G的功能 

                                             


        git reset:将当前的工作目录完全回滚到指定的版本号,假设如下图,我们有A-G五次提交的版本,其中C 的版本号是 bbaf6fb5060b4875b18ff9ff637ce118256d6f20,我们执行了'git reset bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那么结果就只剩下了A-C三个提交的版本

                                              


        git stash:将当前未提交的工作存入Git工作栈中,时机成熟的时候再应用回来,这里暂时提一下这个命令的用法,后面在技巧篇会重点讲解

        git config:利用这个命令可以新增、更改Git的各种设置,例如'git config branch.master.remote origin'就将master的远程版本库设置为别名叫做origin版本库,后面在技巧篇会利用这个命令个性化设置你的Git,为你打造独一无二的 Git

        git tag:可以将某个具体的版本打上一个标签,这样你就不需要记忆复杂的版本号哈希值了,例如你可以使用 'git tag revert_version bbaf6fb5060b4875b18ff9ff637ce118256d6f20'来标记这个被你还原的版本,那么以后你想查看该版本时,就可以使用 revert_version标签名,而不是哈希值了

        Git之所以能够提供方便的本地分支等特性,是与它的文件存储机制有关的。Git存储版本控制信息时使用它自己定义的一套文件系统存储机制,在代码根目录下有一个.git文件夹,会有如下这样的目录结构:

        


 

 

        有几个比较重要的文件和目录需要解释一下:HEAD文件存放根节点的信息,其实目录结构就表示一个树型结构,Git采用这种树形结构来存储版本信息, 那么HEAD就表示根;refs目录存储了你在当前版本控制目录下的各种不同引用(引用指的是你本地和远程所用到的各个树分支的信息),它有heads、 remotes、stash、tags四个子目录,分别存储对不同的根、远程版本库、Git栈和标签的四种引用,你可以通过命令'git show-ref'更清晰地查看引用信息;logs目录根据不同的引用存储了日志信息。因此,Git只需要代码根目录下的这一个.git目录就可以记录完
整的版本控制信息,而不是像SVN那样根目录和子目录下都有.svn目录。那么下面就来看一下Git与SVN的区别吧


5、Git与SVN的不同

        SVN(Subversion)是当前使用最多的版本控制工具。与它相比较,Git最大的优势在于两点:易于本地增加分支和分布式的特性。

        下面两幅图可以形象的展示Git与SVN的不同之处

                                                              


 

                                                                


        对于易于本地增加分支,图中Git本地和服务器端结构都很灵活,所有版本都存储在一个目录中,你只需要进行分支的切换即可达到在某个分支工作的效果。 而SVN则完全不同,如果你需要在本地试验一些自己的代码,只能本地维护多个不同的拷贝,每个拷贝对应一个SVN服务器地址。举一个实际的例子,以前我所 在的小组使用SVN作为版本控制工具,当我正在试图增强一个模块,工作做到一半,由于会改变原模块的行为导致代码服务器上许多测试的失败,所以并没有提交 代码。这时候上级对我说,现在有一个很紧急的Bug需要处理, 必须在两个小时内完成。我只好将本地的所有修改diff,并输出成为一个patch文件,然后回滚有关当前任务的所有代码,再开始修改Bug的任务,等到
修改好后,在将patch应用回来。前前后后要完成多个繁琐的步骤,这还不计中间代码发生冲突所要进行的工作量。可是如果使用Git, 我们只需要开一个分支或者转回到主分支上,就可以随时开始Bug修改的任务,完成之后,只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意,每 一个新的任务都可以开一个分支,完成后,再将它合并到主分支上,轻松而优雅。

        分布式对于Git而言,你可以本地提交代码,所以在上面的图中,Git有利于将一个大任务分解,进行本地的多次提交,而SVN只能在本地进行大量的一 次性更改,导致将来合并到主干上造成巨大的风险。Git的代码日志是在本地的,可以随时查看。SVN的日志在服务器上的,每次查看日志需要先从服务器上下 载下来。我工作的小组,代码服务器在美国,每次查看小组几年前所做的工作时,日志下载就需要十分钟,这不能不说是一个痛苦。后来我们迁移到Git上,利用 Git日志在本地的特性,我用Ruby编写了一个Rake脚本,可以查看某个具体任务的所有代码历史,每次只需要几秒钟,大大方便我的工作。当然分布式并
不是说用了Git就不需要一个代码中心服务器,如果你工作在一个团队里,还是需要一个服务器来保存所有的代码的。

        总结

        本篇介绍了Git的基本概念、一些常用命令和原理,大家可以尝试动手体会一下,下一篇会重点介绍Git命令的使用技巧,Git附带的工具,最后会在Git Hub上创建一个开源项目

SVN

重要:

SVN不是记录每一个版本的实际内容,只是记录版本间的差异

SVN使用延迟拷贝来实现svn copy,其只是原始文件的一个链接,对拷贝的修改被svn记录为相对于原始文件的修改

 

 

1.创建存储库

   假设d:/dev/svnrepo为存放svn存储库的目录

   svnadmin create d:/dev/svnrepo/test   创建一名为test的存储库

2.导入项目

   假设你的项目在d:/dev/eclipse中的Test文件夹,你的当前目录为d:/dev/eclipse,你的svn存储库路径为http://localhost/svn/test

   svn import Test http://localhost/svn/test/OnlyTest -m "Initial Import"

   解释:导入的是Test文件夹下的内容 ;另外,注意要起一个路径名OnlyTest,否则全导入到http://localhost/svn/test下了;-m 为日志

3.导出项目

   svn export <项目文件夹> <你的文件夹>

   svn export -r <version> <项目文件夹> <你的文件夹>

-------------------------

4.取出

   svn co(checkout) http://localhost/svn/test/OnlyTest   ---   将OnlyTest文件夹其下的文件取出来并建立默认文件夹OnlyTest

   svn co -r <url>  -- 取出特定版本

   svn co http://localhost/svn/test/OnlyTest MyTest  -- 将OnlyTest文件夹下的文件取出,放入新建立的文件夹MyTest中

5.添加

  svn add *  --  svn会将未纳入版本控制的文件加入版本控制中(必须svn commit)

  svn add --non-recursive *   非递归添加

6.删除

   svn delete(rm,remove,del) <filename>  -- 删除文件和目录(必须svn commit)

7.提交

   svn commit -m "you log"  -- 提交

   svn commit --changelist <changelist name>  -- 提交指定的changelist

8.创建目录

   svn mkdir <dirname>

   svn mkdir <url>

9.移动文件或目录

   svn move <source_name> <dist_name>

   svn move <source_url> <dist_url>

10.输出特定文件或URL的内容

   svn cat <file or url> --  输出特定文件或URL的内容

   svn cat -r <version> <file or url>

------------------------------

11.显示本地或远程某一文件或目录的详细信息

   svn info <filename>

   svn info -r <version> <filename>

12.列表

   svn list(ls)

   svn list -r <version>

13.当前目录或文件的状态

   svn status <filename>

   svn status --show-updates(或-u)  从项目存储库中找出哪些文件有更新

状态:

第一列:指出条目的状态

空  无改动

A   添加

C   冲突

D   删除

G   合并

M   修改

X    无版本记录,被svn:externals使用

?    未用版本控制管理

第二列:属性状态

空  无改动

C   冲突

M   修改

第三列:工作拷贝是否被锁定

空   未锁

L    锁了

 

14.清理

   svn cleanup  --  递归清理工作拷贝

15.帮助

   svn help

   svn help <subcommand>  -- 显示子命令的帮助,如:svn help add

-----------------------

18.锁定某一目录或文件

   svn propset svn:needs-lock true  <二进制文件>  -- 设定需要锁[svn会将其设置为只读,提示用户编辑这个文件前先加锁]

   svn lock <dir or file>

   svn lock --force <dir or file>  -- 强制对文件加锁,即使此文件已被别人加锁

19.解锁

   svn unlock <dir or file>

   svn unlock --force <dir or file>  -- 可以解锁其他用户锁定的文件

20.显示特定文件和URL每一行的作者和修订版本信息

   svn blame <file or url>  --  每一行文本在开头都放了最后修改的作者(用户名)和修订版本号。

   svn blame -r <version> <file or url>

 

21.更新

   svn update ---- 把版本库的修改带到工作拷贝

   svn update -r<version>  --  改变到某一个版本

状态:

A   添加   add

D   删除   delete

U   更新   update

C   冲突   conflict

M   合并   merge

 

22.找不同

   svn diff <file>  -- 找出工作版本和最后更新的版本中的不同

   svn diff -c <version> <file>   查看文件
<file>
在修订版本<version>修改的内容,是version和version-1比较

   svn diff -r <version> <file>   察看你的工作拷贝对旧的修订版本<version>的修改

   svn diff -r <version1>:<version2> <file> 使用范围符号来比较修订版本<version1>和<version2>

   svn diff -r <version1>:<version2> <url>

   svn diff --changelist <changelist name>

 

23.拷贝

   svn copy <source> <dist>  --  其中source和dist既可以是工作目录文件也可以是url

   如:svn copy foo.txt bar.txt

         svn copy near.txt file:///tmp/repos/test/far-away.txt -m "Remote copy."

         svn copy file:///tmp/repos/test/far-away near-here

         svn copy file:///tmp/repos/test/far-away file:///tmp/repos/test/over-there -m "remote copy."

24. 显示提交日志信息

   svn log -r <version> <path>

   svn log -r <version1>:<version2> <path>

   svn log <path>

   svn log -r {iso8601日期}  <path>

   svn log -r {iso8601日期}:{iso8601日期} <path>

   svn log -v <path>  显示详细的信息(包括每个版本有哪些文件有变动)

   svn log --stop-on-copy <path>  得出分支是什么时候创建的

 

25.删除工作拷贝文件或目录的“冲突”状态(相关的冲突文件文件)

   svn resolved <path>

26.取消所有的本地编辑

   svn revert <path>

   svn revert --recursive <path>  递归

27.解决冲突

   svn resolve --accept <status> <path>

   status:

      base:选择你更新你的工作拷贝前的你checkout出的未经修改的版本

      working:手工处理后,选择当前你工作拷贝中的版本

      mine-full:选择在你svn update前的工作拷贝

      theirs-full:选择svn update取出的文件拷贝

28.将文件放入到一个改变列表中

    svn changelist(cl) <changelist name> <path1> <path2> <path...>

    svn commit --changelist <changelist name> -- 只提交此change list的文件

 

29.版本号标识

(1)号  87

(2){日期}  {2009-09-09}

(3)HEAD  存储库中最新版本

(4)BASE   工作拷贝中你最后签出的版本

(5)COMMITED  最后改动版本,等于或早于BASE

(6)PREV  COMMITED之前的一个版本

 

30.产生和应用补丁

svn diff > file.patch

patch <options> file.patch

 

31.svn项目组织

    project/

        trunk/    --主干

        branches/   --分支

        tags/  --标签

 

32.常用示例

(1)提交改动

svn update  -- 更新到项目的当前状态

# resolve conflicts  解决冲突

  编辑文件

  svn resolved

# run tests  运行测试

svn commit -m "your logs"  -- 提交

(2)简单bug修正

a.在一个分支中修正bug并提交

b.将其合并到存在此bug的其他分支中(svn merge -r<version1>:<version2>)

(3)复杂bug修正

a.创建一个bug修正分支(svn copy)  name=bug-trackid

b.为这个修正分支在修正前打标签(svn copy) name=bugpre-trackid

c.修正bug

d.为这个修正在修正后打标签(svn copy) name=bugpost-trackid

e.合并此bug修正到其他分支(svn merge -r bugpre-trackid:bugpost-trackid)
-------------------------

svn是subversion的客户端

subversion使用的是copy-modify-merge模型,因此一旦我们从subversion服务器获得工作拷贝 (check
out)之后,就可以像修改普通本地文件那样修改这些拷贝。

subversion与vss 6.0(visual sourcesafe)的lock-modify-unlock模型很不一样;它甚至与vss
8.0(visual studio 2005 附带的vss版本)也有一点不一样:对于vss
8.0,获得文件的操作是get
latest version,而请求修改文件的操作是check
out;而subversion的checkout操作不是请求修改文件,而是获得私有的工作拷贝,这个意义上,checkout有点类似于vss的get
latest version,但是subversion并不需要vss的checkout操作,一旦你获得这些工作拷贝之后,你就可以立即开始工作了!
2.常用操作
下面假设subversion仓库的地址是http://server/svn
a) check out

svn checkout http://server/svn 即可在当前目录下建立一个工作拷贝,目录名是svn
b) update
使用命令svn update可以用服务器的版本更新你的工作拷贝
c) add
使用命令 svn add filename可以把filename这个文件或者目录以及目录下面的所有文件标志为添加状态(实际上它并没有立即添加,你可以查看服务器,这些文件都还没有添加进去的!),下一次你提交(commit)这些文件的时候,服务器就会把他们添加到版本库。
d) stat
使用svn stat可以查看文件状态(也就是是否被修改等)
e) commit
使用svn commit filename --message "leave words about this commit",可以提交本地修改到服务器。如果不使用--message选项,则svn会自动打开一个配置文件所指向的编辑器,里面默认有一些修改信息,你可以把这些信息作为附注提交到服务器。或者你也可以不使用--message而使用--file 来指定一个文件作为提交时的附注。
f) switch
有时候管理员修改了版本库的地址,比如修改了主机地址,修改了url等,此时客户端也需要相应的修改:svn
switch --relocate http://xiao/svnhttp://xiao:81/svn第一个地址是原来的版本库地址(用svn
info可以看到),后面的是新的版本库地址
标签:  svn git