<h4>源代码管理工具的起源</h4>
- <h5>为什么会出现
源代码管理工具
?</h5>- 为了解决在软件开发过程中,由源代码引发的各种蛋疼繁琐问题
- <h5>源代码会引发哪些问题?</h5>
- 无法后悔:做错了一个操作后,没有后悔药可吃
- 版本备份:费空间、费时间
- 版本混乱:因版本备份过多造成混乱,难于找回正确的想要的版本
- 代码冲突:多人操作同一文件(团队开发中常见问题)
- 权限控制:无法对源代码进行精确的权限控制
- 追究责任:出现了严重的BUG,无法得知是谁干的
<h4>源代码管理工具的作用</h4>
- 能追踪一个项目从诞生一直到定案的过程
- 记录一个项目的多有内容变化
- 方便地查阅特定版本的修订情况
- ... ...
<h4>常见的源代码管理工具</h4>
- <h5>
CVS
</h5>- 开启版本控制之门
- 1990年诞生,“远古时代”的主流源代码管理工具
- <h5>
SVN
</h5>- 全称是Subversion,集中式版本控制之王者
- 是CVS的接班人,速度比CVS快,功能比CVS多且强大
- 在国内使用率非常高(70%~90%)
- <h5>
GIT
</h5>- 一款伟大的分布式源代码管理工具
- 目前被越来越多的开源项目使用
- 不过在国内企业尚未大规模普及
<h4>SVN</h4>
-
<h5>SVN基本操作</h5>
$ svn checkout:将服务器代码完整的下载到本地
$ svn commit:将本地修改的内容提交到服务器
$ svn update:将服务器最新的代码下载到本地
*注:Checkout只需要做一次!
- 提示:
- 每天下班前:commit一次
“可运行版本代码”
- 每天上班前:update前一天所有代码
- 每天下班前:commit一次
-
<h5>SVN官方基本操作</h5>
- <h5>SVN使用环境</h5>
- 想要使用SVN管理源代码,必须得有2套环境
- <b>
服务器
</b>- 用于存储客户端上传的源代码
- 可以在
Windows
上安装Visual SVN Server
- 大部分情况下,公司的开发人员不必亲自搭建SVN服务器
- <b>
客户端
</b>- 上传本地的源代码到服务器,或者更新服务器的代码到本地,保持同步
- 可以在
Mac
上使用命令行、Versions、Cornerstone、Xcode
- 开发人员就属于客户端这个角色
- <b>
- <h5>SVN客户端命令行演示</h5>
一、初始化项目- 1.项目经理将服务器的已有的内容下载到本地(演示)
$ svn checkout 服务器地址 --username=xxx --password=xxx
- 2.项目经理初始化项目(演示)
-
$ touch main.m
:创建main.m -
$ svn add main.m
:将main.m添加到svn的管理之下 -
$ svn commit -m "xxx"
:将main.m上传到服务器
-
- 3.查看文件状态(查看文件是否在svn的管理下,或者是否进行了修改而没有提交)
$ svn status
- 1.项目经理将服务器的已有的内容下载到本地(演示)
状态说明:描述文件被添加、删除或其他修改
' ' 没有修改
'A' 该文件已经添加到svn的管理之下,但是该文件在本地,并未提交到服务器
'C' 冲突
'D' 被删除
'I' 被忽略
'M' 被修改
'R' 被替换
'X' 外部定义创建的版本目录
'?' 文件没有被添加到本地版本库中,不在svn的管理之下
'!' 文件丢失或者不完整(不识别该文件)
'~' 受控文件被其他文件阻隔
'U' 更新最新的代码到本地(本地有文件的情况下)
'G' 产生冲突后,更新操作去解决冲突,相当于进行合并
- 4.张三加入开发
1>将服务器所有的内容下载到本地
$ svn checkout 服务器地址 --username=xxx --password=xxx
2>开始开发
$ touch person.h person.m
:创建person类
$ svn commit -m "创建了person类"
3>经理更新代码
$ svn update
:更新服务器最新的代码(如果该文件在本地不存在,则下载,如果本地存在,则更新)
- 5.命令行的简写
- svn checkout -> svn co
- svn status -> svn st
- svn commit -> svn ci
- svn update -> svn up
- 6.版本回退
$ svn revert 文件名(person.h)
:将本地新增的内容(没有提交到服务器),删除
$ svn update -r版本号
:先回退到某个版本,观察下,该版本是否是不想要的那个版本,示范:svn update -r6
$ svn update
:更新到最新的版本
$ svn merge -r版本号(hight):版本号(low) 文件名
:示范:svn merge -r7:6 person.h(本地)
*注意:如果本地版本号低于服务器版本号,那么不能提交
$ svn commit -m "回退到版本x"
(服务器) - 7.删除文件
$ svn remove 文件名
:示范:svn remove person.m,svn remove -> svn rm(缩写) - 8.查看版本信息
$ svn update
:更新服务器最新的内容
$ svn log
:查看版本信息 - 9.公司常用的命令
$ svn update
:更新
$ svn commit -m "注释"
:将本地的代码提交到服务器
二、李四加入开发(新员工)
1>需要想项目经理要一些东西
- 和项目经理要服务器地址以及账号地址
- 需求文档:有什么需求,做什么样的功能
- 接口文档:详细的记录服务器所有的功能
- 效果图:界面到底长什么样子
2>将服务器已有的内容下载到本地 -
$ svn checkout 服务器地址 --username=xxx password=xxx
3>代码冲突(out of date
:过期/本地版本号低于服务器的版本) -
(df) diff-full
:在命令行中展示所有的不同 -
(e) edit
:在命令行中来编辑冲突 -
(mc) mine-conflict
:用我本地的代码来覆盖服务器的代码 -
(tc) theirs-conflict
:用服务器的代码来覆盖我的代码 -
(p) postpone
:延迟解决冲突,展示所有冲突的文件,手动解决冲突 ->$ svn resolved 文件名
(person.h)
*注意:如何避免冲突
- 1>尽量在修改文件之前,先update
- 2>如果修改公共文件,最好跟同事说一声,让它先别修改,修改完之后,让他更新>>
- <h5>SVN图形化界面工具</h5>
- 1.项目经理初始化项目
- 1>项目经理将服务器已有的内容下载到本地
- 记住format的选择 -> 1.7(最高)
- 2>需要忽略的文件
- xcuserdata
- xcode会默认记录之前停留文件,下次打开依然停留在该文件,这个不需要共享
- xcode会默认记录之前目录的打开状况,同事不需要共享
- 断点信息,不需要进行共享
- xcuserdata
- 1>项目经理将服务器已有的内容下载到本地
- 2.在xcode中使用svn的注意点
- 1>如果使用到静态库需要特别注意,必须使用命令行将静态库添加到svn的管理之下
- 2>如果使用到了storyboard也需要特别注意
- 如果能使用xib,尽量使用xib
- 如果在项目当中使用到了storyboard,尽量保证只有一个人在操作storyboard
- 3>checkout的方式
- 使用命令行
- 使用cornerstone(图形化界面工具)
- Xcode
- 4>公司开发技巧(避免冲突)
- 尽量写一些代码就提交到服务器,实时跟服务器的代码保持同步
- <h5>目录规范</h5>
- 规范项目的svn目录结构一般有3个文件夹
- trunk:
主干
,当前开发项目的主目录 - branches:
分支
目录,添加非主线功能
时使用,开发测试之后,可以合并到主干项目中 - tags:
标记
目录,通常作为重大的版本的备份
- trunk:
<h4>Git</h4>
- <h5>什么是git?</h5>
- git是一款开源的分布式版本控制工具
- 在世界上所有的分布式版本控制工具中,git是最快、最简单、最流行的
-
<h5>集中式版本控制</h5>
-
<h5>分布式版本控制</h5>
- <h5>git和svn的简单对比</h5>
- 速度:在很多情况下,git的速度远远比svn快
- 结构:svn是集中式管理,git是分布式管理
- 其他:
- svn使用分支比较笨拙,git可以轻松拥有无限分枝
- svn必须联网才能正常工作,git支持本地版本控制工作
- 就版本的svn会在每一个目录放置一个.svn,git只会在根目录拥有一个.git
-
<h5>svn的工作流程</h5>
- 分布式和集中式的最大区别在于:在分布式下
- 开发者可以本地提交
- 每个开发者机器上都有一个服务器的数据库
-
<h5>git的工作流程</h5>
- <h5>git的使用</h5>
- 跟svn一样,你可以通过命令行敲指令或者图像界面客户端使用git
- 在Mac上,比较好用的git图形界面客户端有
- SourceTree
- GitHub
- 下载地址:https://mac.github.com
- 不过它是专门给GitHub网站而设计的
- Xcode
- 几个专用名词的译名:
- Workspace : 工作区
- Index/Stage : 暂存区
- Repository : 本地仓库
- Remote : 远程仓库
- <h5>Git的工作原理</h5>
- 如果想了解git的工作原理,有几个核心概念必须知道
-
工作区(Working Directory)
:仓库文件夹里除了.git目录
以外的内容(项目所在的文件目录) -
版本库(Repository)
:工作区又一个隐藏目录文件.git目录
(可通过命令 ls -ah 查看隐藏文件)这就是Git的版本库,用于存储记录版本信息 暂缓区(stage)
-
分支(master)
:git自动创建的第一个分支 -
HEAD指针
:用于指向当前分枝
-
- <h5>Git的命令行演示</h5>
- 0.安装Git
-
$ brew install git
:Mac -
$ sudo apt-get install git-core
or$ sudo apt-get install git
:Ubuntu or some linux OS
-
- 1.如果使用Git,必须给Git配置用户名和邮箱
- 给当前的git仓库配置用户名和邮箱
$ git config user.name "Vincent"
$ git config user.email "vn_vincent@outlook.com"
- 给git配置全局的用户名和邮箱
$ git config --global user.name "Vincent"
$ git config --global user.email "vn_vincent@outlook.com"
- 2.新建代码库
-
$ mkdir demo
:建立目录 -
$ cd demo
:进入demo目录 -
$ git init
:创建一个本地仓库 -
$ git remote add origin gitAddress
:本地库“关联”远程库 -
$ Git remote remove origin
:取消本地目录下关联的远程库
-
-
$ git clone gitAddress
:从远程仓库克隆项目代码 -
$ git clone -b C gitAddress
:从远程仓库克隆“指定分支C”上的代码 -
$ git pull origin master
:把远端“origin”节点的“master”拉回本机且进行合并
- 3.初始化项目
-
$ touch main.m
:创建了main.m -
$ git add main.m
:将main.m添加到暂缓区(staging area) -
$ git commit -m "初始化项目"
:将在暂缓区的所有内容提交到本地版本库,并清空暂缓区 $ git push -u origin master
-
- 4.增加/删除文件
-
$ git add [file]
:将制定的文件添加到暂存区 -
$ git add .
:添加当前目录下的所有文件 -
$ git add -p
:添加每个变化前,都会要求确认;对于同一个文件的多处变化,可以实现分次提交 -
$ git add -u
:暂存修改和删除的文件,不包括新增的文件 -
$ git add -A
:暂存所有的文件,包括新增的,修改和删除的文件。 -
$ git rm [file1] [file2] ...
:删除工作区为难,并且将这次删除放入暂存区 -
$ git rm -cached [file1] [file2]
:(说法1: 删除本地仓库文件,但不会删除文件);(说法2: 停止追踪指定文件,但该文件回保留在工作区) -
$ git mv [file-original] [file-renamed]
:改名文件,并且将这个改名放入暂存区
*注意:添加的文件或者修改的文件都要通过add命令将该文件添加到暂缓区
-
- 5.代码提交
-
$ git commit -m "first commit"
:提交暂存区刀仓库区 -
$ git commit [file1] [file2] ... -m [message]
:提交暂存区的指定文件到仓库区 -
$ git commit -a
:提交工作区自上次commit之后的变化,直接到仓库区 -
$ git commit -am
:自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过$ git add
步骤,参数 -am 也可写成 -a -m -
$ git commit -v
:提交时显示所有diff(扩展)消息 -
$ git commit -p
:commit文件的一部分,适合工作量比较大的情况。之后,git会对这块修改弹出一个提示,询问你是否stage,按y/n来选择是否commit这块修改,?可以查看其他操作的说明 -
$ git commit --amend
:最终只会有一次提交,第二次提交将代替第一次提交的结果。其使用场景:适用于提交完发现落掉几个文件没添加,或者提交信息写错的情况 -
$ git commit --amend [file1] [file2] ...
:重做上一次commit,并包括指定文件的新变化 -
$ git commit --amend -m [message]
:使用一次新的commit,代替上一次提交;如果代码没有任何新改变,则用来改写上一次commit的提交信息 -
$ git commit --amend --reset-author
:在上一次commit之后想重新更新一下时间。amend实际上修改了上一个commit。所以如果已经push了上一个commit,请尽量不要amend。如果一定要amend已经push了的commit,请确保这个commit所在的branch只有你一个人在使用(负责会给其他人带来灾难),然后在amend之后使用$ git push -force
。只要多加小心,该命令貌似没什么卵用
-
- 6.分支
-
$ git branch A
:创建分支 -
$ git checkout -b A
:创建分支A,并且切换到A分支上 -
$ git checkout B
:切换到B分支上 -
$ git branch -a
:查看所有本地分支和远程分支 -
$ git merge B
:合并指定分支B到当前分支 -
$ git branch -d B
:删除分支 -
$ git push origin --delete B
:删除远程分支B -
$ git branch -dr [remote / branch]
:也是删除远程分支 -
$ git push origin 本地分支A : 远程分支A
将本地分支push到远程分支,并且命名远程分支为A -
$ git fetch origin
:同步远程仓库 -
$ git push -u origin master
:关联后,使用该命令第一次推动master分支的所有内容,后续在推送的时候就可以省略后面三个参数,其中u代表上游(upstream)的意思 -
$ git push --set-upstream origin A
:git提示使用此命令
-
- 7.撤销
-
$ git checkout --文件
:恢复暂存区的指定文件到工作区(丢弃工作区的修改,包括修改后还没有放到暂存区和增加到暂换区后又作了修改两种情况。总之,让该文件会到最后一次$ git commit
或$ git add
之后的状况。注意:没有-,就变成了切换分支的命令了)
- 在还没有add的时候
-
$ git checkout 那个路径下的文件夹或者文件名
:(就能撤销未添加的修改) - 如果已经add过的文件:
-
$ git reset HEAD 那个路径下的文件夹或者文件名
:(就能回到未添加的状态),然后再用$ git checkout [file]
方法撤销修改
-
- 注意:如果你把某个文件删除了,或者是新添加的文件,都不会在恢复或者去掉,但是会把文件中的添加的代码去掉
- 如果已经commit过的文件:
-
$ git reset -hard HEAD^
:那么如果要回退到上上个版本只需把HEAD^
改成HEAD^^
以此类推。那如果要回退到前100个版本的话,使用上面的方法肯定不方便,我们可以使用下面的简单指令操作:$ git reset -hard HEAD~100
即可 - 不过还有一种比较实用的方法:
-
$ git reset -hard [你要回退的版本号]
:这样就能直接回退到你置顶的那一次提交
-
$ git reflog
:可获取到每次提交的版本号
- 已经push过的
- 粗暴的方法:(只需两行命令)
-
$ git reset -hard 1243ad3(commit唯一标识)
或者$ git checkout (commit唯一标识 前7位)
-
$ git push origin HEAD -force
:(强行push)
- +7.改写提交
$git rebase -i HEAD~~
:使用rebase -i命令选择要修改的提交 - 预设文字编辑器会开启从HEAD到HEAD~~的提交,如下图显示内容
pick 9a54fd4 添加commit的說明
pick 0d4a808 添加pull的說明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
将第二行的“pick”
改为“squash”
,存储后并推出,由于合并后要提交,所以编辑器会提示您编辑这个最新的提交讯息,请编辑讯息后存储并提出,
这样,两个提交就合并成一个提交了,请使用log命令确认历史记录
- 8.查看文件状态
$ git status
- 红色:该文件被添加或者被修改,但是没有添加到git的暂缓区
- 绿色:该文件在暂缓区,但是没有提交到本地版本库
- 9.给命令行起别名
$ git config alias.st "status"
$ git config alias.ci "commit -m"
$ git config --global alias.st "status"
- 10.查看版本信息
-
$ git log
:-> 版本号是由sha1算法生成的40位哈希值 -
$ git log -p -2
:除显示基本信息之外,还显示每次提交的内容差异,-2意思是仅显示最近两次提交。特别适用于进行代码审查,或者快速浏览某个搭档提交的commit所带来的变化
-
-
$ git log --graph
:查看分支合并图 -
$ git reflog
:-> 可以查看所有版本会退的操作(比git log功能更强大)
- 11.版本回退:
-
$ git reset --hard HEAD
:回到当前版本 -
$ git reset --hard HEAD^
:回到上一个版本 -
$ git reset --hard HEAD^^
:回到上上个版本 -
$ git reset --hard HEAD~100
:回到前100个版本 $ git reset --hard 版本号(前5位)
-
- 12.给log起别名:
$ git config --global alias.lg "log --color --graph -- pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev- commit"
- git add和git commit的原理
-
$ git add
:把文件修改或者新添加的文件添加到暂缓区 -
$ git commit
:把暂缓区的所有内容提交到当前分枝
-
- <h5>Git常见问题</h5>
-
在使用git对源代码进行push到远程仓库的时候可能会出错,信息如下:
- 此时很多人会尝试下面的命令把当前分支上传到master分支上:
$ git push -u origin master
但是任然没有解决问题。 - 出现错误的主要原因是github/gitlab中的某些文件不在本地代码库目录中,可以通过如下命令进行代码合并【注:pull=fetch+merge】:
git pull --rebase origin master
,如上方法,即可解决err问题。
-
-
注意:git和svn不同,仅仅跟踪文件的变动,不跟踪目录,所以,一个空目录,如果里面没有文件,即便
$ git add
这个目录,另外在别处 checkout 的时候,是没有这个空目录的。- 只跟踪文件变化,不跟踪目录,这么设计是有原因的。但这会带来一些小麻烦。有时候,确实需要在代码仓库中保留某个空目录。比如测试时需要用到的空目录。下面来看看如何解决。
-
- 目录是空的:
- 这种情况下只需要在目录下创建
.gitkeep
文件,然后在项目的.gitignore
中设置不忽略.gitkeep
就可以了 -
.gitkeep
是一个约定俗成的文件名并不会嗲来特殊规则
-
- 目录中一定存在文件
- 这就需要首先在根目录中设置
!.gitignore
,然后在目标目录也创建一个.gitignore
文件,并在文件中设置
*
!.gitignore
git在使用中遇到的问题以及注意点:
1.由于在项目中一般为多人开发,所以在使用git的时候一定要注意:
在更改项目之前,一定要记得先pull项目到最新的版本
如果本地有做项目备份,在
commit->pull->push
的时候确认是否在备份分支做的操作,如果是,请注意,一定要切回主分支然后merge备份分支的内容,-
<h5>Git的共享版本库</h5>
- git服务器的搭建非常繁琐(linux)
- 可以把代码托管到(GitHub/GitLab/OSChina)
- 一个文件夹也可以做共享版本库
- 一个U盘也可以做共享版本库,详见:把Git Repository建到U盘上去
-
1.一个文件夹作为共享版本库
$ git init --bare
-
2.将共享版本库的所有内容下载到本地
$ git clone 共享版本库地址
-
3.删除忽略文件
-
$ touch .gitignore
-> GitHub -> 搜索“.gitignore” -> 选择*最多的 -> 找到Object-C,复制下来
-
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xccheckout
*.xcscmblueprint
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
- 4.版本回退
-
$ git reset --hard HEAD^
:回到上一个版本(张三) -
$ git push -f
:强制上传至共享版本库 -
$ git reset --hard HEAD^
:回到上一个版本(经理)
-
- <h5>Git的版本备份</h5>
- 1.假设Xian1.0版本开发完毕,将1.0版本上传到AppStore,对1.0版本进行备份(打上标签)
$ git tag -a Xian1.0 -m "这是Xian1.0版本"
$ git tag
- 2.需要将标签push到共享版本库
$ git push origin Xian1.0
- 3.开始Xian2.0版本的开发
- 4.发现Xian1.0版本有bug,在经理的文件夹下面创建一个文件夹,用于修复bug,将共享版本库所有内容clon
$ git clone
- 5.将当前的代码转为Xian1.0标签,创建分枝,并切换到该分枝
-
$ git checkout Xian1.0
:转为1.0标签 -
$ git checkout -b Xian1.1fixBug
:创建分枝,并切换到该分枝
-
- 6.在分支中修复bug,上传到AppStore,将修复好的版本,打上tag,并上传至共享版本库
$ git tag -a Xian1.1 -m "这是修复了1.0bug的1.1版本"
$ git push origin Xian1.1
- 7.跟当前正在开发的2.0版本进行合并
- source Control -> pull -> Xian1.1fixBug
- 8.删除分支
-
$ git branch
:查看当前在哪个分支 -
$ git branch -r
:查看本地版本库的分支 -
$ git branch -d Xian1.1fixBug
:删除本地分支 -
$ git branch -r -d origin/Xian1.1fixBug
:删除本地版本库分支 $ git push origin --delete Xian1.1fixBug
-