svn,git的对比以及常用命令上篇
Posted robert_chao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了svn,git的对比以及常用命令上篇相关的知识,希望对你有一定的参考价值。
之前定制Rom,需要下载android源码,修改系统应用。android源码管理使用repo+git,下载速度快的吓人。(直接下载的话,被墙了当然慢,请忽略这个因素)。感觉git更适合大型项目管理。项目经验不是非常多,个人无论大小项目,自己选择的话还是喜欢用git。
个人总结的git优点
1、分支管理非常方便
2、回退,查看历史更加方便,支持命令更多
3、速度更快
4、可以离线提交到本地库,可以离线查看log
5....
下面参照大牛的介绍,来具体看一下git和svn的不同
参考http://stackoverflow.com/questions/871/why-is-git-better-than-subversion
http://stackoverflow.com/questions/964331/git-file-integrity
GIT是分布式的,SVN不是
这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。GIT并不是目前第一个或唯一的分布式版本控制系统。还有一些系统,例如Bitkeeper , Mercurial 等,也是运行在分布式模式上的。但GIT在这方面做的更好,而且有更多强大的功能特征。GIT跟SVN一样有自己的集中式版本库或服务器。但,GIT更倾向于被使用于分布式模式,也就是每个开发人员从中心版本库/服务器上chect out代码后会在自己的机器上克隆一个自己的版本库。,如果被困在一个不能连接网络的地方时,就像在飞机上,地下室,电梯里等,你仍然能够提交文件,查看历史版本记录,创建项目分支,等。对一些人来说,这好像没多大用处,但当突然遇到没有网络的环境时,这个将解决大麻烦。
同样,这种分布式的操作模式对于开源软件社区的开发来说也是个巨大的恩赐,不必再像以前那样做出补丁包,通过email方式发送出去,你只需要创建一个分支,向项目团队发送一个推请求。这能让代码保持最新,而且不会在传输过程中丢失。GitHub.com 就是一个这样的优秀案例。
有些谣言传出来说subversion将来的版本也会基于分布式模式。但至少目前还看不出来。
GIT把内容按元数据方式存储,而SVN是按文件
所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。如果把.git目录的体积大小跟.svn比较,会发现它 们差距很大。因为,.git目录是处于机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。GIT分支和SVN的分支不同
分支在SVN中一点不特别,就是版本库中的另外的一个目录。如果想知道是否合并了一个分支,需要手工运行像这样的命令svn propget svn:mergeinfo ,来确认代码是否被合并。所以,经常会发生有些分支被遗漏的情况。然而,处理GIT的分支却是相当的简单和有趣。可以从同一个工作目录下快速的在几个分支间切换。很容易发现未被合并的分支,能简单而快捷的合并这些文件。
GIT没有一个全局的版本号,而SVN有
目前为止这是跟SVN相比GIT缺少的最大的一个特征。SVN的版本号实际是任何一个相应时间的源代码快照。但是我们可以使用GIT的SHA-1来唯一的标识一个代码快照。这个并不能完全的代替SVN里容易阅读的数字版本号。但,用途应该是相同的。
GIT的内容完整性要优于SVN
GIT的内容存储使用的是SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。以下是svn客户端常用命令一览:
查看最近3个版本日志svn log [PATH] -v -l3
log消息代码 A :added D:deleted M:modified R:replaced
查看某两个版本,用来对比
svn log -r 14:15
添加文件或目录到你的wc,打上新增标记。这些文件会在下一次你提交wc的时候提交到svn服务器。
在提交前,你也可以用svn revert撤销新增的文件。
svn add file.java
取消提交
svn revert --recursive file.java
显示某个已受控文件的每一行的最后修改版本和作者
svn blame file.java
输出指定目标的内容,这里的目标一般是文件。
svn cat file.java 显示file.java内容。
svn cat file.java -r 2 ##显示版本号为二的file.java内容。
svn cat file.java --revision HEAD ##显示最新版本的file.java内容。
将wc中的文件从逻辑上分组.
svn changelist CLNAME TARGET...
svn changelist --remove TARGET
别名:cl
svn cl clName file.java file2.java file3.java ##将file.java等三个文件加入名叫clName的changelist
svn commit --changelist clName -m "ci" ##将clName下的所有文件提交
检出
svn checkout URL[@REV]... [PATH]
别名:co
svn checkout file:///var/svn/repos/test file:///var/svn/repos/quiz working-copies
svn checkout -r 2 file:///var/svn/repos/test mine ##check out 版本号为2的项目
递归的清理WC中过期的锁和未完成的操作
svn cleanup
把你WC的更改提交到仓库
svn commit [PATH...]
别名:ci
svn commit -m "added howto section." ##默认情况下提交必须提供log message
javaopy操作可以从WC到WC;WC到URL;URL到WC;URL到URL。现在SVN只支持同一个仓库内文件的拷贝,不允许跨仓库操作。
svn copy SRC[@REV]... DST
别名:cp
svn copy -r 11 file:///var/svn/repos/test/trunk \\
file:///var/svn/repos/test/tags/0.6.32-prerelease \\
-m "Forgot to tag at rev 11"
##copy命令是创建分支和标记的常用方式。copy到url的操作隐含了提交动作,所以需要提供log messages。
删除
svn delete PATH...
别名:del,remove,rm
访问库:如果PATH是库地址时会,删除WC内的文件不会。
svn del localfile.java ##删除WC里的文件,在下一次提交WC的时候才会真正在仓库里将对应文件删除。
svn del file:///var/svn/repos/test/yourfile ##删除仓库里的文件
比较并显示修改点
svn diff
别名:di
svn diff ##最常用的方式,用来显示WC基于最近一次更新以后的所有的本地修改点。
svn diff -r 301 bin ## 比较WC和版本301中的bin目录的修改点
svn diff -r 3000:3500 file:///var/svn/repos/myProject/trunk ##比较库里主干3000版和3500版的差异。
svn diff --summarize --xml http://svn.red-bean.javaom/repos/test@r2 http://svn.red-bean.javaom/repos/test ##--summarize --xml 参数将差异情况以xml文档的方式显示出来。
导出一个干净的目录树,不包含所有的受控信息。可以选择从URL或WC中导出。
svn export [-r REV] URL[@PEGREV] [PATH]
svn export [-r REV] PATH1[@PEGREV] [PATH2]
访问库:如果访问的是URL则会。
svn export file:///var/svn/repos my-export ##导出到my-export目录。
查看帮助文档
svn help
访问库:否。
导入本地一个目录到库中。但是导入后,本地的目录并不会处于受控状态。
svn import [PATH] URL
别名:无
访问库:是。
svn import -m "New import" myproj http://svn.myProject.javaom/repos/trunk/misc
显示指定WC和URL信息。
svn info [TARGET[@REV]...]
别名:无
访问库:仅当访问的是库路径时。
svn info --xml http://svn.myProject.javaom/repos/test ##将信息以xml格式显示。
显示目标下的文件和目录列表。
svn list [TARGET[@REV]...]
别名:ls
访问库:如果访问的是库地址就会。
svn list --verbose file:///var/svn/repos ##--verbose参数表示显示详细信息。
对目标获得修改锁。如果目标已被其他用户锁定,则会抛出警告信息。用--force参数强制从其他用户那里获得锁。
svn lock TARGET...
别名:无
访问库:是
svn lock --force tree.jpg
合并两个受控源的不同之处,存放到一个WC里。
svn merge sourceURL1[@N] sourceURL2[@M] [WCPATH]
svn merge sourceWCPATH1@N sourceWCPATH2@M [WCPATH]
svn merge [[-c M]... | [-r N:M]...] [SOURCE[@REV] [WCPATH]]
访问库:只有当访问库地址时。
svn merge --reintegrate http://svn.example.javaom/repos/calc/branches/my-calc-branch ##合并分支上的改变项到WC,往往用于分支合并到主干。
svn merge -r 156:157 http://svn.example.javaom/repos/calc/branches/my-calc-branch ##将制定URL版本156到157的所有更新合并到WC。
在WC或库路径创建目录
svn mkdir PATH...
svn mkdir URL...
访问库:只有当访问库地址时。
svn mkdir newdir
svn move SRC... DST
别名:mv, rename, ren
描述:等同于svn copy命令跟个svn delete命令。WC到URL的重命名是不被允许的。
访问库:只有当访问库地址时。
svn move foo.java bar.java ##将foo.java改名成bar.java。
svn propdel PROPNAME [PATH...]
svn propdel PROPNAME --revprop -r REV [TARGET]
别名:pdel, pd
描述:从受控文件,目录等删除属性。第二种是删除某个指定版本上的附加属性。
访问库:只有当访问库地址时。
svn propdel svn:mime-type someFile ##从someFile上移除svn:mime-type这个属性。
svn propedit PROPNAME TARGET...
svn propedit PROPNAME --revprop -r REV [TARGET]
别名:pedit, pe
描述:编辑属性
访问库:只有当访问库地址时。
svn propedit svn:keywords file.java ##修改file.java上的svn:keywords属性。
svn propget PROPNAME [TARGET[@REV]...]
svn propget PROPNAME --revprop -r REV [URL]
别名:pget,pg
描述:从文件,目录或版本取得指定属性的值。
访问库:只有当访问库地址时。
svn propget svn:keywords file.java ##从file.java中取得svn:keywords属性的值
svn proplist [TARGET[@REV]...]
svn proplist --revprop -r REV [TARGET]
别名:plist, pl
描述:列出文件、目录或版本上的所有附加属性
访问库:只有当访问库地址时。
svn proplist --verbose file.java
svn propset PROPNAME [PROPVAL | -F VALFILE] PATH...
svn propset PROPNAME --revprop -r REV [PROPVAL | -F VALFILE] [TARGET]
别名:pset,ps
描述:给文件、目录或版本附加属性并赋值
访问库:只有当访问库地址时。
svn propset svn:mime-type image/jpeg file.jpg ##给file.jpg附加属性svn:mime-type 其值为image/jpeg
svn propset --revprop -r 25 svn:log "Journaled about trip to New York."
##给版本25补上log message
svn propset svn:ignore '.javalasspath' .
##在本地忽略掉.javalasspath文件
svn resolve PATH...
别名:无
描述:将冲突的文件标记为已解决,并且删掉冲突产生的临时文件。注意这个命令并不是能把冲突解决,解决冲突还是得靠人工。
访问库:否
svn resolve --accept mine-full foo.java ##1.5版本后,加上--accept参数,尝试自动处理冲突。
svn resolved PATH...
别名:无
描述:已过时,被resolve --accept取代。去除冲突的状态和冲突临时文件。
访问库:否
svn revert PATH...
别名:无
描述:还原WC中所有的本地更改。
访问库:否
svn revert --depth=infinity . ##将整个目录所有文件还原
svn status [PATH...]
别名:stat, st
描述:输出WC中文件和目录的状态。如果WC提交,这些状态就会同步到库里。
一般状态有 ' ' 没有修改
'A' 新增
'D' 删除
'M' 修改
'R' 替代
'C' 冲突
'I' 忽略
'?' 未受控
'!' 丢失,一般是将受控文件直接删除导致
访问库:加上--show-updates参数时会
svn status wc
svn switch URL[@PEGREV] [PATH]
svn switch --relocate FROM TO [PATH...]
别名:sw
描述:将WC转向一个其他的库地址同步
访问库:是
svn sw http://svn.myProject.javaom/repos/trunk/vendors . ##将当前WC切换到另一个URL
svn unlock TARGET...
别名:无
描述:解锁
访问库:是
svn unlock somefile
svn update [PATH...]
别名:up
描述:更新WC,更新反馈有如下几种分类。
A 新增
B 锁破坏
D 删除
U 更新
C 冲突
G 合并
E 存在的
访问库:是
svn up -r22 ##更新到一个指定版本
创建分支
svn cp -m "create branch" http://svn_server/xxx_repository/trunk http://svn_server/xxx_repository/branches/br_feature001
获得分支
svn co http://svn_server/xxx_repository/branches/br_feature001
合并主干上的最新代码到分支上
cd br_feature001
svn merge http://svn_server/xxx_repository/trunk
如果需要预览该刷新操作,可以使用svn mergeinfo命令,如:
svn mergeinfo http://svn_server/xxx_repository/trunk --show-revs eligible
或使用svn merge --dry-run选项以获取更为详尽的信息。
分支合并到主干
一旦分支上的开发结束,分支上的代码需要合并到主干。SVN中执行该操作需要在trunk的工作目录下进行。命令如下:
cd trunk
svn merge --reintegrate http://svn_server/xxx_repository/branches/br_feature001
分支合并到主干中完成后应当删该分支,因为在SVN中该分支已经不能进行刷新也不能合并到主干。
合并版本并将合并后的结果应用到现有的分支上
svn -r 148:149 merge http://svn_server/xxx_repository/trunk
建立tags
产品开发已经基本完成,并且通过很严格的测试,这时候我们就想发布给客户使用,发布我们的1.0版本
svn copy http://svn_server/xxx_repository/trunk http://svn_server/xxx_repository/tags/release-1.0 -m "1.0 released"
删除分支或tags
svn rm http://svn_server/xxx_repository/branches/br_feature001
svn rm http://svn_server/xxx_repository/tags/release-1.0
一、 Git 命令初识
在正式介绍Git命令之前,先介绍一下Git 的基本命令和操作,对Git命令有一个总体的认识示例:从Git 版本库的初始化,通常有两种方式:
1、git clone:这是一种较为简单的初始化方式,当你已经有一个远程的Git版本库,只需要在本地克隆一份
例如:git clone https://github.com/robertjc/simplealgorithm.git
上面的命令就是将'https://github.com/robertjc/simplealgorithm.git'这个URL地址的远程版本库,完全克隆到本地。
2、git init 和 git remote:这种方式稍微复杂一些,当本地创建了一个工作目录,可以进入这个目录,使用'git init'命令进行初始化;Git以后就会对该目录下的文件进行版本控制,这时候如果需要将它放到远程服务器上,可以在远程服务器上创建一个目录,并把可访问的URL记录下来,此时你就可以利用'git remote add'命令来增加一个远程服务器端,
例如:git remote add orign git://github.com/someone/another_project.git
上面的命令就会增加URL地址为'git: //github.com/someone/another_project.git',名称为origin的远程服务器,以后提交代码的时候只需要使用 origin别名即可
二、 Git 常用命令
1、远程仓库相关命令
检出仓库: $ git clone https://github.com/robertjc/simplealgorithm.git查看远程仓库:$ git remote -v
添加远程仓库:$ git remote add [name] [url]
删除远程仓库:$ git remote rm [name]
修改远程仓库:$ git remote set-url --push [name] [newUrl]
拉取远程仓库:$ git pull [remoteName] [localBranchName]
推送远程仓库:$ git push [remoteName] [localBranchName]
*如果想把本地的某个分支test提交到远程仓库,并作为远程仓库的master分支,或者作为另外一个名叫test的分支,如下:
$git push origin test:master // 提交本地test分支作为远程的master分支
$git push origin test:test // 提交本地test分支作为远程的test分支
2、分支(branch)操作相关命令
查看本地分支:$ git branch查看远程分支:$ git branch -r
创建本地分支:$ git branch [name] ----注意新分支创建后不会自动切换为当前分支
切换分支:$ git checkout [name]
创建新分支并立即切换到新分支:$ git checkout -b [name]
删除分支:$ git branch -d [name] ---- -d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D选项
合并分支:$ git merge [name] ----将名称为[name]的分支与当前分支合并
创建远程分支(本地分支push到远程):$ git push origin [name]
删除远程分支:$ git push origin :heads/[name] 或 $ gitpush origin :[name]
*创建空的分支:(执行命令之前记得先提交你当前分支的修改,否则会被强制删干净没得后悔)
$git symbolic-ref HEAD refs/heads/[name]
$rm .git/index
$git clean -fdx
3、版本(tag)操作相关命令
查看版本:$ git tag创建版本:$ git tag [name]
删除版本:$ git tag -d [name]
查看远程版本:$ git tag -r
创建远程版本(本地版本push到远程):$ git push origin [name]
删除远程版本:$ git push origin :refs/tags/[name]
合并远程仓库的tag到本地:$ git pull origin --tags
上传本地tag到远程仓库:$ git push origin --tags
创建带注释的tag:$ git tag -a [name] -m 'yourMessage'
4、子模块(submodule)相关操作命令
添加子模块:$ git submodule add [url] [path]如:$git submodule add git://github.com/robertjc/project.git src/main/src/com/robert
初始化子模块:$ git submodule init ----只在首次检出仓库时运行一次就行
更新子模块:$ git submodule update ----每次更新或切换分支后都需要运行一下
删除子模块:(分4步走哦)
1) $ git rm --cached [path]
2) 编辑“.gitmodules”文件,将子模块的相关配置节点删除掉
3) 编辑“ .git/config”文件,将子模块的相关配置节点删除掉
4) 手动删除子模块残留的目录
5、忽略一些文件、文件夹不提交
在仓库根目录下创建名称为“.gitignore”的文件,写入不需要的文件夹名或文件,每个元素占一行即可,如target
bin
*.db
三、 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的索引中,该功能类似于SVN的add
git rm:从当前的工作空间中和索引中删除文件,例如'git rm app/model/user.rb',该功能类似于SVN的rm、del
git commit:提交当前工作空间的修改内容,类似于SVN的commit命令,例如'git commit -m story #3, add user model',提交的时候必须用-m来输入一条提交信息,该功能类似于SVN的commit
git push:将本地commit的代码更新到远程版本库中,例如'git push origin'就会将本地的代码更新到名为orgin的远程版本库中
git log:查看历史日志,该功能类似于SVN的log
git revert:还原一个版本的修改,必须提供一个具体的Git版本号,例如'git revert ccaf6fb6060b4875b18ff9ff637ce118256d6f20',Git的版本号都是生成的一个哈希值
上面的命令几乎都是每个版本控制工具所公有的,下面就开始尝试一下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/readme.txt'就会将readme.txt文件从上一个已提交的版本中更新回来,未提交的内容全部会回滚
git rebase:通常用于在向别处推送提交之前对它们进行重写。交互式rebase提供了一个简单易用的途径让你在和别人分享提交之前对你的提交进行分割、合并或者重排序。在把从其他开发者处拉取的提交应用到本地时,也可以使用交互式rebase对它们进行清理
git reset:将当前的工作目录完全回滚到指定的版本号
git stash:将当前未提交的工作存入Git工作栈中
git config:利用这个命令可以新增、更改Git的各种设置
git config --global user.name "robert"
git config --global user.email 805467553@qq.com
https方式每次都要输入密码,按照如下设置即可输入一次就不用再手输入密码的困扰而且又享受https带来的极速
设置记住密码(默认15分钟):
git config --global credential.helper cache
如果想自己设置时间,可以这样做:
git config credential.helper 'cache --timeout=3600'
这样就设置一个小时之后失效
长期存储密码:
git config --global credential.helper store
git tag:可以将某个具体的版本打上一个标签,这样就不需要记忆复杂的版本号哈希值了
四、git的Patch功能
git提供了两种简单的patch方案。一是用git diff生成的标准patch,二是git format-patch生成的Git专用Patch。1.git diff生成的标准patch
新建fix分支,并切换到该分支git branch Fix
git checkout Fix
修改完成之后,打补丁
git diff master > patch
git checkout master
我们现在有一个patch文件,并且签出了master,接下来我们可以使用git apply来应用这个patch。当然了,实际应用中,我们不会这样在一个分支建patch,到另一个分支去应用,因为只有merge一下就好了。我们现 在权当没有这个Fix分支。一般情况下,为了保护master,我们会建立一个专门处理新交来的patch的分支:
新建branch分支,并切换到该分支,应用补丁
git branch PATCH
git checkout PATCH
git apply patch
现在我们在PATCH分支中应用了这个补丁,我们可以把PATCH分支和Fix比对一下,结果肯定是什么也没有,说明PATCH分支和Fix分支完全一样。patch应用成功。即使有多个文件git diff 也能生成一个patch。
2.git format-patch生成的git专用补丁。
# git format-patch -M master // 当前分支所有超前master的提交# git format-patch -s 4e16 // 某次提交以后的所有patch, --4e16指的是SHA1 ID
# git format-patch -1 // 单次提交
# git format-patch -3 // 从master往前3个提交的内容,可修改为你想要的数值
# git format-patch –n 07fe // -n指patch数,07fe对应提交的名称, 某次提交(含)之前的几次提交
# git format-patch -s --root origin // 从origin到指定提交的所有patch
应用patch:
先检查patch文件:# git apply --stat newpatch.patch
检查能否应用成功:# git apply --check newpatch.patch
打补丁:# git am --signoff < newpatch.patch
(使用-s或--signoff选项,可以commit信息中加入Signed-off-by信息)
或git am
3.两种patch的比较:
兼容性:很明显,git diff生成的Patch兼容性强。如果你在修改的代码的官方版本库不是Git管理的版本库,那么你必须使用git diff生成的patch才能让你的代码被项目的维护人接受。除错功能:对于git diff生成的patch,你可以用git apply --check 查看补丁是否能够干净顺利地应用到当前分支中;如果git format-patch 生成的补丁不能打到当前分支,git am会给出提示,并协助你完成打补丁工作,你也可以使用git am -3进行三方合并,详细的做法可以参考git手册或者《Progit》。从这一点上看,两者除错功能都很强。
版本库信息:由于git format-patch生成的补丁中含有这个补丁开发者的名字,因此在应用补丁时,这个名字会被记录进版本库,显然,这样做是恰当的。因此,目前使用Git的开源社区往往建议大家使用format-patch生成补丁。
通常集成开发环境都有集成svn,git相关插件,提供可视化操作。
欢迎扫描二维码,关注公众账号
以上是关于svn,git的对比以及常用命令上篇的主要内容,如果未能解决你的问题,请参考以下文章