版本管理:SVN(Cornerstone)、Git(Sourcetree)

目录
    1. SVN(Cornerstone工具)
    2. Git(Sourcetree工具)

1. SVN

Apache Subversion(SVN)是一个开源的版本控制系统。

  1. 相关概念
Subversion 在 2000 年由 CollabNet Inc 开发。

SVN相对于RCS、CVS,采用了分支管理系统,它的设计目标就是取代CVS。
SVN管理着随时间改变的数据, 这些数据放置在一个中央资料档案库(repository) 中。 这个档案库很像一个普通的文件服务器, 不过它会记住每一次文件的变动,这样就可以把档案恢复到旧的版本或浏览文件的变动历史。 
1. repository(源代码库)
源代码统一存放的地方

2. Checkout(提取)
当手上没有源代码的时候,需要从repository checkout一份

3. Update (更新)
当已经Checkout了一份源代码, Update一下就可以和Repository上的源代码同步,手上的代码就会有最新的变更。

4. Commit(提交)
当已经修改了代码,就需要Commit到repository

5. 如果两个程序员同时修改了同一个文件, SVN 可以合并这两个程序员的改动,实际上SVN管理源代码是以行为单位的,就是说两个程序员只要不是修改了同一行程序,SVN都会自动合并两种修改。如果是同一行,SVN 会提示文件 Conflict, 冲突,需要手动确认。

主要功能

1. 目录版本控制
CVS 只能跟踪单个文件的历史。
Subversion是一个 "虚拟" 的版本控管文件系统, 能够依时间跟踪整个目录的变动,目录和文件都能进行版本控制。

2. 真实的版本历史
自从CVS限制了文件的版本记录,CVS并不支持那些可能发生在文件上,但会影响所在目录内容的操作,如复制和重命名。除此之外,在CVS里不能用拥有同样名字但是没有继承老版本历史或者根本没有关系的文件替换一个已经纳入系统的文件。
在Subversion中,可以增加(add)、删除(delete)、复制(copy)和重命名(rename),无论是文件还是目录。所有的新加的文件都从一个新的、干净的版本开始。

3. 自动提交
一个提交动作,不是全部更新到了档案库中,就是不完全更新。这允许开发人员以逻辑区间建立并提交变动,以防止当部分提交成功时出现的问题。

4. 纳入版本控管的元数据
每一个文件与目录都附有一組属性关键字并和属性值相关联。可以创建并儲存任何想要的Key/Value对。 属性是随着时间来作版本控管的,就像文件內容一样。

5. 选择不同的网络层
Subversion 有抽象的档案库存取概念, 可以让人很容易地实作新的网络机制。 Subversion 可以作为一个扩展模块嵌入到Apache HTTP 服务器中。这个为Subversion提供了非常先进的稳定性和协同工作能力,除此之外还提供了许多重要功能: 举例来说, 有身份认证, 授权, 在线压缩, 以及文件库浏览等等。还有一个轻量级的独立Subversion服务器, 使用的是自定义的通信协议, 可以很容易地通过 ssh 以 tunnel 方式使用。

6. 一致的数据处理方式
Subversion 使用二进制差异算法来异表示文件的差异, 它对文字(人类可理解的)与二进制文件(人类无法理解的) 两类的文件都一视同仁。 这两类的文件都同样地以压缩形式储存在档案库中, 而且文件差异是以两个方向在网络上传输的。

7. 有效的分支(branch)与标签(tag)
在分支与标签上的消耗并不必一定要与项目大小成正比。 Subversion 建立分支与标签的方法, 就只是复制该项目, 使用的方法就类似于硬连接(hard-link)。 所以这些操作只会花费很小, 而且是固定的时间。

8. Hackability
Subversion没有任何的历史包袱; 它主要是一群共用的 C 程序库, 具有定义完善的API。这使得 Subversion 便于维护, 并且可被其它应用程序与程序语言使用。

相对CVS的优势

1. 原子提交。
一次提交不管是单个还是多个文件,都是作为一个整体提交的。在这当中发生的意外例如传输中断,不会引起数据库的不完整和数据损坏。

2. 重命名、复制、删除文件等动作都保存在版本历史记录当中。

3. 对于二进制文件,使用了节省空间的保存方法。(简单的理解,就是只保存和上一版本不同之处)。

4. 目录也有版本历史。
整个目录树可以被移动或者复制,操作很简单,而且能够保留全部版本记录。

5. 分支的开销非常小。

6. 优化过的数据库访问,使得一些操作不必访问数据库就可以做到。这样减少了很多不必要的和数据库主机之间的网络流量。

工作流程

1. 创建版本库
版本库相当于一个集中的空间,用于存放开发者所有的工作成果。版本库不仅能存放文件,还包括了每次修改的历史,即每个文件的变动历史。
Create 操作:创建一个新的版本库。当创建一个新的版本库时,版本控制系统会让你提供一些信息来标识版本库,例如创建的位置和版本库的名字。大多数情况下这个操作只会执行一次。

2. 检出
Checkout操作:从版本库下载代码到工作副本。工作副本是开发者私人的工作空间,可以进行内容的修改,然后提交到版本库中。

3. 更新
Update操作:将版本库中的最新代码更新到工作副本。

4. 执行变更
当检出之后就可以做很多操作(编辑/添加/删除文件、目录)来执行变更。这些改变会被添加进待变更列表中,直到执行了 Commit 操作后才会成为版本库的一部分。
Rename操作:可以更改文件/目录的名字。
"移动"操作用来将文件/目录从一处移动到版本库中的另一处。

5. 复查变化
在 commit 操作之前复查下修改是一个很好的习惯。
Status操作 : 列出了工作副本中所进行的变动(待变更列表),但并不提供变动的详细信息。可以用 diff 操作来查看这些变动的详细信息。

6. 修复错误
Revert 操作 : 重置对工作副本的修改。
可以重置一个或多个文件/目录、整个工作副本。

7. 解决冲突
合并的时候可能会发生冲突。
Merge 操作:自动处理可以安全合并的东西。其它的会被当做冲突。例如,"hello.m" 文件在一个分支上被修改,在另一个分支上被删除了。这种情况就需要人为处理。
Resolve操作: 用来帮助用户找出冲突并告诉版本库如何处理这些冲突。

8. 提交更改
Commit 操作: 用来将更改从工作副本提交到版本库。
在提交之前,你必须将文件/目录添加到待变更列表中。列表中记录了将会被提交的改动。
当提交的时候,通常会提供一个注释来说明为什么会进行这些改动。这个注释也会成为版本库历史记录的一部分。Commit 是一个原子操作,也就是说要么完全提交成功,要么失败回滚。用户不会看到成功提交一半的情况。
  1. SVN使用
查看是否安装SVN(mac默认已经安装)
svn --version
  1. 在服务端进行SVN版本库的相关配置
1. 创建版本库

mkdir /opt/svn
// 创建版本库
svnadmin create /opt/svn/runoob
// 启动服务
// -r: 配置方式决定了版本库访问方式。
// --listen-port: 指定SVN监听端口,不加此参数,SVN默认监听3690
svnserve -d -r 目录 --listen-port 端口号

/**
方式一:-r直接指定到版本库(单库svnserve方式)
svnserve -d -r /opt/svn/runoob
这种情况下,一个svnserve只能为一个版本库工作。

authz配置文件中对版本库权限的配置应这样写:
[groups]
admin=user1
dev=user2
[/]
@admin=rw
user2=r

svn://192.168.0.1/ 访问runoob版本库
*/
/**
方式二:指定到版本库的上级目录(多库svnserve方式)
svnserve -d -r /opt/svn
这种情况下,一个svnserve可以为多个版本库工作。

authz配置文件中对版本库权限的配置应这样写:
[groups]
admin=user1
dev=user2
[runoob:/]
@admin=rw
user2=r
[runoob01:/]
@admin=rw
user2=r

svn://192.168.0.1/runoob 访问runoob版本库
*/
2. 修改默认配置文件配置(conf目录下的svnserve.conf)

[general]
// 控制非鉴权用户访问版本库的权限,取值范围为write读写、read只读(默认)、none无访问权限。
anon-access = none
// 控制鉴权用户访问版本库的权限。默认:write。
auth-access = write
// 用户名口令文件,默认为conf目录中的passwd
password-db = /home/svn/passwd
// 指定权限配置文件名,通过该文件可以实现以路径为基础的访问控制。 除非指定绝对路径,否则文件位置为相对conf目录的相对路径。 默认为conf目录中的authz 。
authz-db = /home/svn/authz
// realm: 指定版本库的认证域,即在登录时提示的认证域名称。若两个版本库的 认证域相同,建议使用相同的用户名口令数据文件。 默认值:一个UUID(Universal Unique IDentifier,全局唯一标示)。 
realm = tiku 
3. 修改用户名口令文件

[users]
admin = admin
thinker = 123456
4. 修改权限配置文件
该配置文件由一个[groups]配置段和若干个版本库路径权限段组成。

[groups]
g_admin = admin,thinker

[runoob01:/]
@g_admin=rw
user2=r

[test:/home/thinker]
thinker = rw
* = r
  1. 客户端(方式1: 终端命令)
1. 检出(从远程服务器端下载项目)
svn checkout svn://192.168.0.1/runoob01 --username=user01

2. 修改文件后
// 查看更改
svn diff 
// 查看工作副本的状态
// 文件的状态为?,说明它是新建的文件,还未加到版本控制中
// 文件的状态为A,说明它加到版本控制中了
// 文件的状态为M,说明它被修改了(在版本控制中)
svn status
// 将?状态的文件添加到版本控制中
svn add file1 
// 更新本地代码。svn update -r6指定更新版本
svn update 
// 提交代码
// 如果冲突,则先解决冲突(去除冲突代码)后再提交
svn commit -m "注释"

3. 回退
// 回退文件到未修改状态
svn revert file1
// 回退目录到未修改状态
svn revert -R 目录1
// 撤销回之前的版本(撤销旧版本里的所有更改然后提交一个新版本)。
svn merge -r 版本号2:版本号1 file1

4. 查看历史信息
// 查看svn的版本、作者、日期、路径等
svn log
// 查看版本6-8
svn log -r 6:8
// 查看某一个文件的版本修改信息
svn log file1
// 包含目录信息,且只要5条
svn log -l 5 -v 
// 查看特定修改的行级详细信息
svn diff
// 比较工作副本和版本库中版本号为3的文件file1
svn diff -r 版本号3 file1
// 比较版本库中版本号为2和3的文件file1
svn diff -r 版本号2:版本号3 file1
// 取得在特定版本的某文件显示在当前屏幕
svn cat -r 版本号1 file1 
// 显示一个目录或某一版本存在的文件
svn list http://192.168.0.1/runoob01

5. 分支
// 创建分支
svn copy 主干线目录/ branches/分支干线目录
// 提交新分支到版本库
svn commit -m "添加分支"
cd跳到分支目录下开发,修改、更新、提交后,再cd跳回到主分支目录下
// 合并到主分支后,然后更新、提交
svn merge ../branches/分支干线目录/

6. 标签(tag)
// 在本地工作副本创建一个 tag。会在tags目录下创建新的目录v1.0
svn copy 主分支目录/ tags/v1.0
// 提交
svn commit -m "创建tag" 
  1. 客户端(方式2: Cornerstone工具)
Cornerstone工具界面

建立远程仓库链接
1. 建立远程仓库链接,并下载项目


<1> 新建仓库:点击 add Repository 
<2> SVN服务器经过Apache映射,则可使用HTTP Server,否则使用SVN Server
    Server:服务器地址
    Port:服务器端口
    Path:文件路径
    Name:账号名
    Password:账号密码
<3> Check Out 下载到本地(从SVN服务器中即远程仓库中下载项目到本地)
2. 本地修改文件后


修改文件后(M表示有修改)
    Update      更新
    Commit      提交到服务器(要勾选pro.pbxproj)

添加文件后(A表示新建)
    点击新建的文件 右击 Add to Working Copy 【破解版需此步骤】
    Update      更新
    Commit      提交到服务器(要勾选pro.pbxproj)

删除文件后(D表示删除) 
    Update      更新
    Commit      提交到服务器(要勾选pro.pbxproj)
3. 出现冲突:(C表示冲突)

    1. 文件内容冲突:   
         从文件中找到有======或 <<<<<<或>>>>>>>的地方 删掉;
         右键冲突文件 | Resolve Conflicts

    2.工程文件冲突: 
         点击工程文件显示包内容,从project.pbxproj文件中找到有======或 <<<<<<或>>>>>>>的地方 删掉;
         右键冲突文件 | Resolve Conflicts

    3.添加文件后,右键有?的文件 |  add to working Copy

1. Git

Git 是一个开源的分布式版本控制系统。


名词说明:

1. Workspace:工作区
2. Index(Stage):暂存区,存放在.git/index文件
3. Repository:仓库区(或本地仓库),.git目录。HEAD是指向分支的游标,指向最后一次提交。
4. Remote:远程仓库
  1. 相关概念

Git 与常用的版本控制工具 CVS, SVN 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。

Git记录版本历史只关心文件数据的整体是否发生变化。Git 不保存文件内容前后变化的差异数据。

实际上,Git 更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git 不会再次保存,而只对上次保存的快照作一连接。

在分布式版本控制系统中,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。这类系统都可以指定和若干不同的远端代码仓库进行交互。借此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程。

另外,因为Git在本地磁盘上就保存着所有有关当前项目的历史更新,并且Git中的绝大多数操作都只需要访问本地文件和资源,不用连网,所以处理起来速度飞快。用SVN的话,没有网络或者断开VPN你就无法做任何事情。但用Git的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程的镜像仓库。

Git 与 SVN 区别

 1、Git 和其它非分布式的版本控制系统(SVN、CVS)最核心的区别:
Git是分布式。
SVN是集中式。
集中式的版本控制系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。


2、Git 把内容按元数据方式存储,而 SVN 是按文件。
所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。


3、Git 分支和 SVN 的分支不同。
分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录。
Git 和 Svn 的分支实现机制完全的不同,这也直接导致了 SVN 在分支合并中困难重重。尽管在 SVN 1.5 之后,通过 svn:mergeinfo 属性引入了合并追踪机制,但是在特定情况下,合并仍会出现很多困难。
/*
1.SVN的分支合并
当你在一个分支上工作数周或几个月之后,主干的修改也同时在进行着,两条线的开发会区别巨大,当你想合并分支回主干,可能因为太多冲突,已经无法轻易合并你的分支和主干的修改。
另一个问题,SVN不会记录任何合并操作,当你提交本地修改,版本库并不能判断出你是通过svn merge还是手工修改得到这些文件。所以你必须手工记录这些信息(说明合并的特定版本号或是版本号的范围)。
要解决以上的问题只有通过有规律的将主干合并到分支来避免,制定这样一个政策:每周将上周的修改合并到分支,注意这样做时需要小心,你必须手工记录合并的过程,以避免重复的合并,你需要小心的撰写合并的日志信息,精确的描述合并包括的范围。这样做看起来有点像是胁迫。
SVN 的版本号是连续的版本号。每一次新的提交都会版本号+1 ,而无论这个提交是在哪个分支中进行的。SVN一个提交可以同时修改不同分支的不同文件,因为提交命令可以在 /trunk, /branches, /tags 的上一级目录执行。
• SVN 的提交是单线索的,每一个提交(最原始的提交0除外)都只有一个父节点(版本号小一个的提交节点)
• SVN 的提交链只有一条,仅从版本号和提交说明,我们无法获得分支图
• SVN 的分支图在某些工具(如乌龟SVN)可以提供,那是需要对提交内容进行检查,对目录拷贝动作视为分支,对 svn:mergeinfo 的改动视为合并,但这会由于目录管理的灵活性,导致千奇百怪的分支图表。

 
2.Git的分支合并
在 git 版本库中创建分支的成本几乎为零,所以,不必吝啬多创建几个分支。当第一次执行git-init时,系统就会创建一个名为”master”的分支。 而其它分支则通过手工创建。
常见的分支策略:
① 创建一个属于自己的个人工作分支,以避免对主分支 master 造成太多的干扰。 
② 当进行高风险的工作时,最好创建一个临时分支。 
③ 合并别人修改时,最好创建一个临时分支用来合并,合并完成后再“fatch”到自己的分支。
*/


4、Git 没有一个全局的版本号,而 SVN 有。
目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。
SVN的全局版本号和CVS的每个文件都独立维护一套版本号相比,是一个非常大的进步。SVN提供对于事物处理的支持,每一个事物处理(即一次提交)都具有整个版本库全局唯一的版本号。
Git的版本号则更进一步,版本号是全球唯一的。Git 对于每一次提交,通过对文件的内容或目录的结构计算出一个SHA-1 哈希值,得到一个40位的十六进制字符串,Git将此字符串作为版本号。
/*
• 所有保存在Git 数据库中的数据都是用此40位的哈希值作索引的,而不是靠文件名。

• 使用哈希值作版本号的好处就是对于一个分布式的版本控制系统,每个人每次提交后形成的版本号都不会出现重复。另一好处是保证数据的完整性,因为哈希值是根据内容或目录结构计算出来的,所以我们还可以据此来判断数据内容是否被篡改。

• SVN 的版本号是连续的,可以预判下一个版本号,而 Git 的版本号则不是。
因为 subversion 是集中式版本控制,很容易实现版本号的连续性。Git 是分布式的版本控制系统,而且 Git 采用 40 位长的哈希值作为版本号,每个人的提交都是各自独立完成的,没有先后之分(即使提交有先后之分,也由于PUSH/PULL的方向和时机而不同)。Git 的版本号虽然不连续,但是是有线索的,即每一个版本都有对应的父版本(一个或者两个),进而可以形成一个复杂的提交链

• Git 的版本号简化:Git 可以使用从左面开始任意长度的字串作为简化版本号,只要该简化的版本号不产生歧义。一般采用7位的短版本号(只要不会出现重复的,你也可以使用更短的版本号)。
*/

5、Git 的内容完整性要优于 SVN。
Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

6、版本库与工作区
SVN的版本库和工作区是分离的(不同的主机中),只能通过 https, http, svn 等协议访问,而不能直接被用户接触到。
/*
• Subversion的工作区是一份版本库在某个历史状态下的快照,如:版本库最新的数据检出到工作区。

• Subversion的工作区中每一个目录下都包含一个名为 .svn 的控制目录(隐藏的目录),该目录的作用是:
① 标识工作区和版本库的对应关系。
② 包含一份该子目录下检出文件的原始拷贝。当文件改动的差异比较或者本地改动的回退时,可以直接参考原始拷贝而无须通过网络访问远程版本库。

• Subversion 的 .svn 控制目录会引入很多麻烦:
① .svn 下的文件原始考本,会导致在目录下按照文件内容搜索时,多出一倍的搜索时间和搜索结果。
② .svn 很容易在集成时,引入产品中,尤其是 Web 应用,将 .svn 目录带入Web服务器会导致安全隐患。因为一个不允许目录浏览的Web目录,可以通过 .svn/entries 文件查看到该目录下可能存在的文件。
*/
Git 的版本库和工作区在同一个目录下,工作区的根目录有一个.git的子目录,这个名为 .git的目录就是版本库本身,它是Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。所以千万要小心删除这个文件。
/*
• 工作区中其他文件为工作区文件,可能是从 .git 中检出的,或者是要检入的,或者是运行产生的临时文件等。

• 版本库可以脱离工作区而存在,成为 bare(赤裸)版本库。可以用 –bare 参数来创建。但是工作区不能脱离版本库而存在,即工作区的根目录下必须有一个名为 .git 的版本库克隆文件。

• Git 的版本库因为就在工作区中,能直接被用户接触到。
① 用户可以编辑 .git/config 文件,修改配置,增添新的源
② 用户可以编辑 .git/info/exclude 文件,创建本地忽略…

• Git 的工作区中只在工作区的根目录下有一个 .git 目录,此外再无任何控制目录。Git 工作区下唯一的 .git 目录是版本库,并非 .svn 的等价物,如果删除了 .git 目录,而又没有该版本库的其他镜像(克隆)的话,你破坏了整个历史,版本库也永远的失去了。

• Git 在本地的 .git 版本库,提供了完全的改动历史。除了和其他人数据交换外,任何版本库相关的操作都在本地完成,更多的本地操作,避免了冗长的网络延迟,大大节省了时间。例如:查看 log,切换到任何历史版本等操作都无须连接网络。

• Git如何保证安全:本地创建一个Git库,因为工作区和库是在同一个目录中,如果工作区删除了,或者所在的磁盘分区格式化了,数据不是全都没有了么?其实我们可以这样做:
① 在一个磁盘分区中创建版本库(最好是用 –bare 参数创建),然后在另外的磁盘分区中克隆一个新的作为工作区。在工作区的提交要不时的PUSH到另外分区的版本库,这样就实现了本地的数据镜像。你甚至可以在本地创建更多的版本库镜像,安全性要比Subversion的一个库加上一个工作区安全。
② 另一个办法:把你的版本库共享给他人,当他人克隆了你的版本库时,你就拥有了一个异地备份。
*/


7、权限管理
  SVN通过对文件目录授权来实现权限管理,子目录默认继承父目录的权限。但是也有缺憾,即权限不能在分支中继承,不能对单个文件授权。
  Git做不到类似SVN的路径授权(不符合分布式理念),授权模型只能实现非零即壹式的授权,要么拥有全部的写权限,要么没有写权限,要么拥有整个版本库的读权限,要么禁用。
/*
Git解决授权:
  1. 公司内部代码开放。
  即代码在公司内部,对项目组成员一视同仁的开放。
  2. 公司对代码库进行合理分解,对每个代码库分别授权。
  即某个代码库对团队成员完全开放,对其它团队完全封闭。
  3. 公司使用SVN做集中式的版本控制,个人和/或团队使用 Git-svn。
  这样在无法改变公司版本控制策略时,程序员可以采用的变通之法。
  4. Git服务器的部署实际上可以使用钩子对分支和路径进行写授权,即可以控制谁能够创建分支,能够写特定文件。
*/


8. 部分检出
SVN可以将整个库检出到工作区,也可以将某个目录检出到工作区。
Git只能全部检出,不支持按照目录进行的部分检出。
/*
1. SVN的部分检出
• 在SVN中,从仓库checkout的一个工作树,每个子目录下都维护着自己的.svn目录,记录着该目录中文件的修改情况以及和服务器端仓库的对应关系。所以SVN可以checkout部分路径下的内容(部分检出),而不用checkout整个版本库或分支。
• SVN 有一条命令:svn export ,可以将 SVN 版本库的一个目录下所有内容导出到指定的目录下。SVN 需要 svn export 命令是因为该命令可以导出一个干净的目录,即不包含 .svn 目录(包含配置文件和文件原始拷贝)。

2. Git的检出
• Git 没有部分检出,这并不是说只有将整个库克隆下来才能查看文件。
有很多 git 工具,提供直接浏览git库的功能,例如 gitweb, trac 的 git 版本库浏览, redmine 的 git 版本库浏览。
• Git-submodule 可以实现版本库的模块化:Git 通过子模块处理这个问题。
子模块允许你将一个Git 仓库当作另外一个Git仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。
• Git 为什么没有实现 svn export 的功能?由于git的本地仓库信息完全维护在project根目录的.git目录下,(不像svn一样,每个子目录下都有单独的.svn目录)。所以,只要clone,checkout然后删除.git目录就可以了。
*/

9. 撤消操作
/*
1.提交的撤销
SVN中一旦完成向服务器的数据提交,就没有办法再从客户端追回,只能在后续的提交中修正(回退或者修改)等。因为Subversion作为集中式的版本控制,不能允许个人对已提交的数据进行篡改。SVN具有一个非常重要的特性就是它的信息从不丢失,即使当你删除了文件或目录,它也许从最新版本中消失了 ,但这个对象依然存在于历史的早期版本中。
Git则不同,Git是分布式版本控制系统,代码库是属于个人,允许任意修改。Git通过对提交建立数字摘要来保证提交的唯一性和不可更改性,通过版本库在多人之间的多份拷贝来保障数据的安全性。Git可以丢弃最新的一个或几个提交,使用 git reset –hard命令可以永远丢弃最新的一个或者几个提交。


2.提交说明的修改
提交后如果对提交说明不满意
⑴ Git可以使用命令git commit –amend修改提交说明。
• Git可以修改最后一次提交说明,并不是说不能修改历史版本的提交说明,只是修改最后一个版本提交说明拥有最简单的命令;
• Git修改提交说明,会改变提交的commit-id。即修改提交说明后,将产生一个新的提交;
• Git可以通过git reset –hard ,git commit –amend,git rebase onto 等命令来实现对历史提交的修改;
• 使用stg工具可以更为简单的修改历史提交的提交说明,包括提交内容;
⑵ SVN也可以修改提交说明,是通过修改提交的svn:log版本属性实现的:
• 不但可以修改最后一次提交的说明,并且可以修改历史提交的提交说明;
• SVN修改提交说明是不可逆的操作,可能会造成说明被恶意修改;
• SVN缺省关闭修改提交说明的功能。管理员在设置了提交说明更改的邮件通知后,才可以打开该功能。

3.修改和重构历史提交
Git可以修改和重构历史提交:使用Git本身的reset以及 rebase 命令可以修改或者重整/重构历史提交,非常灵活。使用强大的 stg 可以使得历史提交的重构更为简洁,如果您对 stg 或者 Hg/MQ 熟悉的话。
SVN 修改历史提交,只能由管理员完成。
SVN 是集中式版本控制系统,从客户端一旦完成提交,就没有办法从客户端撤销提交。但是管理员可以在服务器端完成提交的撤销和修改,但是操作过程和代价较大。
*/

10. 更新和提交
/*
1.更新操作
在SVN中,因为只有一个中心仓库,所以所谓的远程更新,也就是svn update ,通过此命令来使工作区和版本库保持同步。
在git中,别人的改动是存在于远程仓库上的,所以git checkout命令尽管在某些功能上和svn中的update类似(例如取仓库特定版本的内容),但是在远程更新这一点上,还是不同的,不属于git checkout的功能涵盖范围。 Git使用git fetch和git pull来完成远程更新任务,fetch操作只是将远程数据库的object拷贝到本地,然后更新remotes head的refs,git pull 的操作则是在git fetch的基础上对当前分支外加merge操作。


2.SVN中的commit命令
对于SVN来说,由于是中心式的仓库管理形式,所以并不存在特殊的远程提交的概念,所有的commit操作都可以认为是对远程仓库的更新动作。在工作区中对文件进行添加、修改、删除操作要同步到版本库,必须使用 commit命令。
• add 命令,是将未标记为版本控制状态的文件标记为添加状态,并在下次提交时入库。
• delete命令,是通过SVN来删除文件,并在下次提交后有效。
• SVN 有提交列表功能,即将某些文件加入一个修改列表,提交可以只提交处于该列表的文件。


3.Git中的暂存区域(stage)
Git 管理项目时,文件在三个工作区域中流转:Git 的本地数据目录,工作目录以及暂存区域。暂存区域(stage)是介于 workcopy 和 版本库  HEAD 版本的一种中间状态。所谓的暂存区域只不过是个简单的文件,一般都放在git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
要将一个文件纳入版本管理的范畴,首先是要用git  add将文件纳入stage的监控范围,只有更新到stage中的内容才会在commit的时候被提交。另外,文件本身的改动并不会自动更新到stage中,每次的任何修改都必须重新更新到stage中去才会被提交。对于工作区直接删除的文件,需要用 git rm 命令进行标记,在下次提交时,在版本库中删除。
• 工作区的文件改动(新增文件,修改文件,删除文件),必须用 git add 或者 git rm 命令标识,使得改动进入 stage
• 提交只对加入 stage 的改动进行提交
• 如果一个文件改动加入 stage 后再次改动,则后续改动不改变 stage。即该文件的改动有两个状态,一个是标记到 stage 中并将在下次提交时入库的改动,另外的后续改动则不被提交,除非再次使用 git add 命令将改动加入到 stage 中。
• Git的stag让你在提交的时候清楚的知道git将要提交哪些改动。除非提交的时候使用 -a 参数(不建议使用)。

我们可以从文件所处的位置来判断其状态:如果是git目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态,如果取出后未进行修改则是未修改状态。
在git中,因为有本地仓库和remote仓库之分,所以也就区别于commit 操作,存在额外的push命令,用于将本地仓库的数据更新到远程仓库中去。git push 可以选择需要提交的、更新的分支以及制定该分支在远程仓库上的名字。
*/

11. 分支和里程碑的实现
几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。在很多版本控制系统中,这是个昂贵的过程,常常需要创建一个源代码目录的完整副本,对大型项目来说会花费很长时间。
轻量级分支/里程碑的含义是,创建分支/里程碑的复杂度是o(1),不会因为版本库的愈加庞大而变得缓慢。在CVS中,创建分支的复杂度是o(n)的,导致大的版本库的的分支创建非常缓慢。
/*
1.SVN的分支/里程碑
SVN轻量级分支和里程碑的实现是通过svn cp命令,即带历史的拷贝就是创建快速创建分支和里程碑的秘籍。SVN的版本库有特殊的设计,当你复制一个目录,你不需要担心版本库会变得十分巨大—SVN并不是拷贝所有的数据,相反,它只是建立了一个已存在目录树的入口。这种“廉价的拷贝”就是创建分支/里程碑是轻量级的原因。
由于SVN的分支和标签是来自目录拷贝,约定俗成是拷贝在 branches/和tags/目录下。所谓分支,tag等概念都只是仓库中不同路径上的一个对象或索引而已,和普通的路径并没有什么本质的区别,谁也不能阻止在一个提交中同时修改不同分支中的数据。
里程碑是对某个历史提交所起的一个别名,作为历史的标记,是不应该被更改的。svn的里程碑要建立到 tags/目录下,要求不要在tags/下的里程碑目录下进行提交。但是谁也阻止不了对未进行权限控制的里程碑的篡改。

 
2.Git 的轻量级分支和里程碑
Git中的分支实际上仅是一个包含所指对象校验和(40个字符长度SHA-1 哈希值)的文件,所以创建和销毁一个分支就变得非常廉价。说白了,新建一个分支就是向一个文件写入41个字节(版本号外加一个换行符)那么简单,自然速度就很快了。 Git的实现与项目复杂度无关,它永远可以在几毫秒的时间内完成分支的创建和切换。这和大多数版本控制系统形成了鲜明对比。
Git的分支是完全隔离的,而SVN则没有。分支本来就应该是相对独立的命名空间,一个提交一般只能发生在一个分支中。在Git中,其内部的对象层级依赖关系或许和SVN类似,但是其工作树的视图表现形式和SVN完全不同。工作树永远是一个完整的分支,不同的分支由不同的head索引去构建,你不可能在工作树中同时获得多个分支的内容。
Git使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。① 轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。② 而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用GNU Privacy Guard (GPG) 来签署或验证。
Git的里程碑是只读的,Git完全遵守历史不可更改这一时空法则。用户不能向git的里程碑中提交,否则里程碑就不是标记,而成了一个分支。当然Git允许用户删除里程碑再重新创建指定到不同历史提交。

 
3.多分支间的切换
SVN中提供了一个功能switch,使用switch可以在同一个工作树上,在不同的分支中进行切换。
Git在分支中进行切换使用的命令是checkout。
*/
SVN的特点
  1. 每个版本库有唯一的URL(官方地址),每个用户都从这个地址获取代码和数据;
  2. 获取代码的更新,也只能连接到这个唯一的版本库,同步以取得最新数据;
  3. 提交必须有网络连接(非本地版本库);
  4. 提交需要授权,如果没有写权限,提交会失败;
  5. 提交并非每次都能够成功。如果有其他人先于你提交,会提示“改动基于过时的版本,先更新再提交”… 诸如此类;
  6. 冲突解决是一个提交速度的竞赛:手快者,先提交,平安无事;手慢者,后提交,可能遇到麻烦的冲突解决。
  7. 原理上只关心文件内容的具体差异。每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容。

SVN的优点
  每个人都可以一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限。
  1. 管理方便,逻辑明确。
  2. 易于管理,集中式服务器更能保证安全性。
  3. 代码一致性非常高。 
  4. 适合开发人数不多的项目开发。

SVN的缺点
  中央服务器的单点故障。若是宕机一小时,那么在这一小时内,谁都无法提交更新、还原、对比等,也就无法协同工作。如果中央服务器的磁盘发生故障,并且没做过备份或者备份得不够及时的话,还会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,被客户端提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人提取出来。
  1. 服务器压力太大,数据库容量暴增。
  2. 如果不能连接到服务器上,基本上不可以工作,如果服务器不能连接上,就不能提交,还原,对比等等。 
Git的特点
   1. Git中每个克隆的版本库都是平等的。可以从任何一个版本库的克隆来创建属于自己的版本库,同时只要你愿意,你的版本库也可以作为源提供给他人。
   2. Git的每一次提取操作,实际上都是一次对代码仓库的完整备份。
   3. 提交完全在本地完成,无须别人给你授权,你的版本库你作主,并且提交总是会成功。
   4. 甚至基于旧版本的改动也可以成功提交,提交会基于旧的版本创建一个新的分支。
   5. Git的提交不会被打断,直到你的工作完全满意了,PUSH给他人或者他人PULL你的版本库,合并会发生在PULL和PUSH过程中,不能自动解决的冲突会提示您手工完成。
   6. 冲突解决不再像是SVN一样的提交竞赛,而是在需要的时候才进行合并和冲突解决。
   7. Git 也可以模拟集中式的工作模式
   8. Git版本库统一放在服务器中
   9. 可以为 Git 版本库进行授权:谁能创建版本库,谁能向版本库PUSH,谁能够读取(克隆)版本库
   10. 团队的成员先将服务器的版本库克隆到本地;并经常的从服务器的版本库拉(PULL)最新的更新;
   11. 团队的成员将自己的改动推(PUSH)到服务器的版本库中,当其他人和版本库同步(PULL)时,会自动获取改变
   12. Git 的集中式工作模式非常灵活
   13. 你完全可以在脱离Git服务器所在网络的情况下,如移动办公/出差时,照常使用代码库
   14. 你只需要在能够接入Git服务器所在网络时,PULL和PUSH即可完成和服务器同步以及提交
   15. Git提供 rebase 命令,可以让你的改动看起来是基于最新的代码实现的改动
   16. Git 有更多的工作模式可以选择,远非SNV可比

Git的优点
    1. 适合分布式开发,强调个体。 
    2. 公共服务器压力和数据量都不会太大
    3. 速度快、灵活
    4. 任意两个开发者之间可以很容易的解决冲突
    5. 离线工作

Git的缺点
    1. 代码保密性差,一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息。

Git配置

1. /etc/gitconfig 文件
系统中对所有用户都普遍适用的配置。
若使用 git config 时用 --system 选项,读写的就是这个文件。

2. ~/.gitconfig 文件
用户目录下的配置文件只适用于该用户。
若使用 git config 时用 --global 选项,读写的就是这个文件。

3. 当前项目的 Git 目录中的配置文件(工作目录下的 .git/config 文件)
这里的配置仅仅针对当前项目有效。

每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。

工作流程

1. 克隆 Git 资源作为工作目录。
2. 在克隆的资源上添加或修改文件。
3. 如果其他人修改了,可以更新资源。
4. 在提交前查看修改。
5. 提交修改。
6. 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
  1. Github

Github是一个基于Git的代码托管平台(最流行的开源托管服务),付费用户可以建私人仓库,免费用户只能使用公共仓库(代码要公开)。

Github 由Chris Wanstrath, PJ Hyett 与Tom Preston-Werner三位开发者在2008年4月创办。

第一步:
注册github账号。网址:https://github.com/


第二步:
创建仓库


第三步:
由于本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以需要配置验证信息。
在本地创建ssh key。终端输入以下命令然后一路回车: 
ssh-keygen -t rsa -C "github上注册的邮箱"
成功的话会在~/目录下生成.ssh文件夹,进入该目录并打开id_rsa.pub,复制里面的key,并在Github个人中心的设置中添加ssh key,粘贴。

验证是否成功,终端输入以下命令(第一次会提示是否continue,输入yes)
ssh -T git@github.com
设置username和email(每次提交时会记录谁提交的), 终端输入以下命令,
git config --global user.name "yourName"
git config --global user.email "your_email@youremail.com"

新建目录
git init

关联远程仓库(origin后面的仓库地址,在Github上复制)
git remote add origin 仓库地址.git

这时在.git/config文件中会多出来,使用git config -e可查看
  [remote "origin"]
        url = 仓库地址.git
        fetch = +refs/heads/*:refs/remotes/origin/*

检出仓库
git clone 仓库地址.git
创建仓库1
创建仓库2
配置SSH Key
仓库的ssh地址

Gitee(国内的 Git 托管服务,5人以下小团队免费)

国内访问Github速度比较慢,很影响使用。
Gitee 提供免费的 Git 仓库,还集成了代码质量检测、项目演示等功能。对于团队协作开发,Gitee 还提供了项目管理、代码托管、文档管理的服务。

网址:https://gitee.com
新建仓库
新建仓库
SSH密钥
仓库地址

Git 服务器搭建(自己搭建一台 Git 服务器作为私有仓库使用)

以 Centos 为例搭建 Git 服务器

1、安装Git
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-devel
yum install git
创建一个git用户组和用户,用来运行git服务
groupadd git
useradd git -g git

2、创建证书登录
把所有需要登录的用户的公钥导入到/home/git/.ssh/authorized_keys文件里
$ cd /home/git/
$ mkdir .ssh
$ chmod 755 .ssh
$ touch .ssh/authorized_keys
$ chmod 644 .ssh/authorized_keys

3、初始化Git仓库
首先选定一个目录作为Git仓库,假定是/home/gitrepo/runoob.git,在/home/gitrepo目录下输入命令:
$ cd /home
$ mkdir gitrepo
$ chown git:git gitrepo/
$ cd gitrepo
$ git init --bare runoob.git
以上命令Git创建一个空仓库,服务器上的Git仓库通常都以.git结尾。然后,把仓库所属用户改为git:
$ chown -R git:git runoob.git

4. 客户端克隆
git clone git@服务器IP:/home/gitrepo/runoob.git
  1. Git使用方式1: 终端命令
辅助命令 说明
git help 帮助
git blame file1 以列表的形式查看指定文件的修改记录(什么人什么时间修改过)
git log 查看当前分支的提交日志
git log --oneline 查看当前分支的提交日志(简洁版本)
git log --reverse 逆向显示所有日志
git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges 指定日期。也可以用 --until 和 --since。--no-merges 参数:隐藏合并提交。
git log --author=Linus --oneline -5 查找指定用户的提交日志
git log --graph 查看历史中什么时候出现了分支、合并。
git log -5 --pretty --oneline 显示过去5次提交
git log --stat 显示提交日志,以及每次提交发生变更的文件
git log -S keyword1 根据关键词搜索提交历史
git log tag1 HEAD --pretty=format:%s 显示某个提交之后的所有变动,每个提交占据一行
git log tag1 HEAD --grep feature 显示某个提交之后的所有变动,其"提交说明"必须符合搜索条件
git log --follow file1 显示某个文件的版本历史,包括文件改名
git log -p file1 显示指定文件相关的每一次diff
git shortlog -sn 显示所有提交过的用户,按提交次数排序
git whatchanged file1 显示某个文件的版本历史,包括文件改名
git status 查看工作区文件状态
git diff 暂存区和工作区的不同(查看尚未暂存的更新)
git diff file1 比较文件的不同(暂存区和工作区)
git diff --cached 暂存区和本地仓库的不同
git diff --cached file1 比较文件的不同(暂存区和本地仓库)
git diff HEAD 工作区和本地仓库的不同
git diff HEAD file1 比较文件的不同(工作区和本地仓库)
git diff [first-branch]...[second-branch] 本地仓库两次提交的不同
git diff --shortstat "@{0 day ago}" 显示今天写了多少行代码
git show commit1 显示某次提交的元数据和内容变化
git show --name-only commit1 显示某次提交发生变化的文件
git show commit1:file1 显示某次提交时,某个文件的内容
git reflog 显示当前分支的最近几次提交
git ls-files 查看已经被提交的文件
远程同步 说明
git remote add origin git@路径.git 关联远程仓库和本地仓库,并命名为origin
git remote remove origin 移除远程仓库关联origin
git remote rename old_name new_name 修改远程仓库名
git remote set-url --push origin git@路径.git 修改远程仓库地址
git remote 查看远程仓库关联名
git remote -v 查看所有远程仓库地址
git remote show origin 查看远程库origin信息
git fetch origin 下载远程仓库的所有变动,之后还需要紧跟着执行git merge和本地分支合并
git merge origin/master 合并远程分支到当前本地分支
git pull origin master 从远程仓库origin的master分支拉取代码和当前本地分支合并。git pull 其实就是 git fetch 和 git merge FETCH_HEAD 的简写。
git pull origin master:dev 从远程仓库origin的master分支拉取代码和本地分支dev合并。
git push origin master 将当前本地分支推送到远程仓库origin的master分支并合并(若master不存在则新建)
git push origin dev:master 将dev本地分支推送到远程仓库origin的master分支,如果本地分支名与远程分支名相同,则可以省略冒号。
git push origin --force 强行推送当前分支到远程仓库,即使有冲突
git push origin --all 推送所有分支到远程仓库
git push origin --delete master 删除远程仓库分支master
新增/删除文件 说明
git add file 添加文件或目录至暂存区(之后才能提交到本地仓库)。以空格分隔文件名
git add . 添加所有文件至暂存区
git add -p 分次提交(确认每个变化)
git rm file 删除工作区文件,并将这次删除放入暂存区(将文件从暂存区和工作区中删除),如果之前修改过已经在暂存区则需要-f强制删除
git rm --cached file 停止追踪指定文件(直接从暂存区删除文件,但会保留在工作区)
git rm –r * 如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件。这里是当前目录下
git mv oldName newName 移动或重命名文件、目录,并将这次更改放入暂存区
代码提交 说明
git commit -m '注释' 提交暂存区到本地仓库
git commit file1 -m '注释' 提交暂存区指定文件到本地仓库。以空格分隔文件名。
git commit -am '注释' 提交工作区自上次commit之后的变化,直接到仓库区,不需要git add了。
git commit -v 提交时显示所有diff信息
git commit --amend file1 重做上一次commit,并包括指定文件的新变化
git commit --amend -m [message] 使用一次新的commit,替代上一次提交
分支相关 说明
git branch 查看所有本地分支
git branch -r 查看所有远程分支
git branch -a 查看所有分支(本地和远程)
git checkout dev 切换到本地分支dev
git checkout - 切换到上一个分支
git branch new old 从本地分支old创建新分支new
git branch new 从当前本地分支创建新的本地分支(并不会自动切换)
git checkout -b dev 从当前本地分支创建新的本地分支并切换到新分支
git checkout -b dev origin/dev 新建本地分支并切换,从远程dev分支
git branch --track branch remote-branch 新建本地分支,与指定的远程分支建立追踪关系
git branch --set-upstream branch remote-branch 在现有分支与指定的远程分支之间建立追踪关系
git branch -m old new 将本地分支old更名为new
git branch -d dev 删除本地分支dev
git branch -dr origin/dev 删除远程分支origin/dev
git push origin 推送本地分支到远程仓库
git push origin --delete dev 删除远程分支dev
git merge dev 将本地dev分支和当前分支合并,发生冲突后手动解决冲突代码后,然后add->commit。
git cherry-pick commit1 选择一个commit,合并进当前分支
git diff branch1 branch2 查看差异
配置相关 说明
git config --list 查看配置内容
git config -e [--global] 编辑Git配置文件。没有global则修改的是当前项目的配置文件,有则是当前用户目录下的配置文件。
git config [--global] user.name "[name]" 修改配置:用户名。
git config [--global] user.email "[email address]" 修改配置:邮箱
git config --global merge.tool vimdiff 在解决合并冲突时使用哪种差异分析工具。kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff。
tag版本标签 说明
git tag 查看所有版本标签tag
git show tag1 查看tag信息
git tag tag1 创建版本标签tag
git tag tag1 commit1 新建一个tag在指定commitID,git log可获取commitID(忘记打标签了,查询过去的提交,然后打标签), 可以少输入几位,只要能确定唯一
git tag -a tag1 -m '注释' 创建带注释的版本标签tag
git tag -d tag1 删除版本标签tag
git push origin tag1 上传本地tag
git push origin --tags 上传所有本地tag到远程仓库
git push origin :refs/tags/tag1 删除远程tag
git pull origin --tags 合并远程仓库的tag到本地
git checkout -b dev tag1 新建一个本地分支dev,指向某个tag1
撤销 说明
git checkout . 恢复暂存区的所有文件到工作区(危险)
git checkout file1 恢复暂存区的指定文件到工作区(危险)
git checkout commit1 file1 恢复某个commit的指定文件到暂存区和工作区,commit的id可通过git log查看
git checkout HEAD . 用 HEAD 指向的分支中的全部或者部分文件替换暂存区和以及工作区中的文件(危险)
git checkout HEAD file1 用 HEAD 指向的分支中的文件替换暂存区和以及工作区中的文件(危险)
git reset file1 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
git reset HEAD 重置暂存区,工作区不受影响(默认为--mixed参数)。HEAD 表示当前版本,HEAD^^^ 上上上一个版本,HEAD~1 上一个版本
git reset HEAD^ 重置暂存区所有内容到上一个版本
git reset HEAD^ hello.php 重置暂存区 hello.php 文件的版本到上一个版本
git reset 052e 重置暂存区到指定版本
git reset --soft HEAD~3 回退上上上一个版本
git reset --hard 重置暂存区与工作区,与上一次commit保持一致(撤消上一次commit的内容)
git reset –hard HEAD~3 回退上上上一个版本 (谨慎使用 –hard 参数,它会删除回退点之前的所有信息)
git reset –hard bae128 回退到某个版本回退点之前的所有信息。
git reset --hard origin/master 将本地的状态回退到和远程的一样
git reset commit1 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
git reset --hard commit1 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
git reset --keep commit1 重置当前HEAD为指定commit,但保持暂存区和工作区不变
git revert commit1 新建一个commit,用来撤销指定commit,后者的所有变化都将被前者抵消,并且应用到当前分支
git stash 暂时将未提交的变化移除,稍后再移入
git stash pop 暂时将未提交的变化移除,稍后再移入
其他命令 说明
git init 初始化git仓库(会生成一个隐藏的 .git 目录,该目录包含了资源的所有元数据)。Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令。默认创建一个master分支。
git clone git@git路径.git 从远程仓库当前分支拉取代码到本地(当前目录下)
git clone git@git路径.git 目录名 从远程仓库当前分支拉取代码到本地(指定目录)
git archive 文件归档打包
git bisect 二分查找
git cat-file 版本库对象研究工具
git citool 图形化提交,相当于 git gui 命令
git clean 清除工作区未跟踪文件
git describe 通过里程碑直观地显示提交ID
git difftool 调用图形化差异比较工具
git format-patch 创建邮件格式的补丁文件。参见 git am 命令
git grep 文件内容搜索定位工具
git gui 基于Tcl/Tk的图形化工具,侧重提交等操作
git mergetool 图形化冲突解决
git rebase 分支变基
git rebase–interactive 交互式分支变基
git rev-parse 将各种引用表示法转换为哈希值等
git add–interactive 交互式添加
git apply 应用补丁
git am 应用邮件格式补丁

从远程仓库下载项目

初始化git仓库
git init

从远程仓库当前分支拉取代吗到本地
git clone git@git路径.git 

把本地项目上传到Github

初始化git仓库(在项目根目录)
git init

把当前目录下的所有文件添加到暂存区
git add .

提交到本地仓库(-m后跟注释)
git commit -m 'first commint'

关联远程仓库和本地仓库
git remote add origin git@路径.git

查看.ssh目录下是否有id_rsa.pub文件,然后复制其内容在远程仓库配置SSH。
// 如果没有运行 ssh-keygen -t rsa -C "chenxiang698@sina.com" 生成。
cd /Users/cx/.ssh/ 

从远程仓库拉取
git pull origin master

推送到远程仓库
git push origin master
// git push origin dev:master     本地dev:远程master

可能遇到的错误

错误1:The authenticity of host 'e.coding.net (118.126.70.252)' can't be established.
解决:输入yes回车

错误2: fatal: refusing to merge unrelated histories
解决:git pull origin master --allow-unrelated-histories

错误3:error: src refspec master does not match any
解决:git push origin dev:master 
git命令

丢弃在本地的所有改动与提交,到服务器上获取最新的版本历史,并将本地主分支指向它

git fetch origin
git reset --hard origin/master
  1. Git使用方式2: Sourcetree(Git)
Sourcetree 界面1(本地仓库列表)
Sourcetree 界面2(具体项目)
说明

  1. 提交:将项目代码提交到本地仓库
  2. 拉取:将远程仓库代码更新到本地仓库
  3. 推送:将本地仓库代码更新到远程仓库
  4. 分支:用于多人开发,区分人员、版本
  5. 合并:合并分支
  6. 克隆:将代码从远程仓库拉取到本地仓库。
    一般刚克隆下来,默认是master分支,需要从远程分支检出Developer分支或新建分支
  7. 检出:本地分支检出是切换不同分支,远程分支检出是拉取远程仓库的代码到本地
  8. 重置:将代码还原到指定时间轴
  9. 未暂存文件:只会保留在缓存区,不会提交到本地仓库,勾选后会转到已暂存文件。已暂存文件:会提交到本地仓库。
  10. 双击本地分支,可进行分支切换
  11. 可以在终端进行以上相关操作

新建本地仓库

如果是导入本地项目
  选择`添加已经存在的本地库`。

如果是导入github项目
  选择`从URL克隆`。

回滚

1. 回滚某一次提交的部分代码
  点击历史  |  点击要回滚的提交  |  点击要回滚的类  |  点击回滚区块或者选中行后点击右上方的回滚行。

2. 回滚某一次提交的全部代码
  选中要回滚的提交,右键,选择提交回滚
回滚某一次提交的部分代码
回滚某一次提交提交

拉取完代码后冲突

解决完冲突后再提交

通常情况下造成冲突是因为修改了同一文件。

分支

新建分支
删除分支

参考文章
参考文章
参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容