关于版本控制
html
什么是“版本控制”?我为何要关心它呢? 版本控制是一种记录一个或若干文件内容变化,以便未来查阅特定版本修订状况的系统。 在本书所展现的例子中,咱们对保存着软件源代码的文件做版本控制,但实际上,你能够对任何类型的文件进行版本控制。node
若是你是位图形或网页设计师,可能会须要保存某一幅图片或页面布局文件的全部修订版本(这或许是你很是渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。 有了它你就能够将某个文件回溯到以前的状态,甚至将整个项目都回退到过去某个时间点的状态,你能够比较文件的变化细节,查出最后是谁修改了哪一个地方,从而找出致使怪异问题出现的缘由,又是谁在什么时候报告了某个功能缺陷等等。 使用版本控制系统一般还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样能够轻松恢复到原先的样子。 但额外增长的工做量却微乎其微。python
本地版本控制系统mysql
许多人习惯用复制整个项目目录的方式来保存不一样的版本,或许还会更名加上备份时间以示区别。这么作惟一的好处就是简单。不过坏处也很多:有时候会混淆所在的工做目录,一旦弄错文件丢了数据就无法撤销恢复。linux
为了解决这个问题,人们好久之前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差别。git
其中最流行的一种叫作 rcs,现今许多计算机系统上都还看获得它的踪迹。甚至在流行的 Mac OS X 系统上安装了开发者工具包以后,也可使用 rcs 命令。它的工做原理基本上就是保存并管理文件补丁(patch)。文件补丁是一种特定格式的文本文件,记录着对应文件修订先后的内容变化。因此,根据每次 修订后的补丁,rcs 能够经过不断打补丁,计算出各个版本的文件内容。github
集中化的版本控制系统算法
接下来人们又遇到一个问题,如何让在不一样系统上的开发者协同工做?因而,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存全部文件的修订版本,而协同工做的人们都经过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这 已成为版本控制系统的标准作法。sql
这种作法带来了许多好处,特别是相较于老式的本地 VCS 来讲。如今,每一个人均可以在必定程度上看到项目中的其余人正在作些什么。而管理员也能够轻松掌控每一个开发者的权限,而且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。数据库
事分两面,有好有坏。这么作最显而易见的缺点是中央服务器的单点故障。若是宕机一小时,那么在这一小时内,谁都没法提交更新,也就没法协同工做。要 是中央服务器的磁盘发生故障,碰巧没作备份,或者备份不够及时,就仍是会有丢失数据的风险。最坏的状况是完全丢失整个项目的全部历史更改记录,而被客户端 提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证全部的数据都已经有人事先完整提取出来过。本地版本控制系统也存在相似问题,只要整个项 目的历史记录被保存在单一位置,就有丢失全部历史更新记录的风险。
分布式版本控制系统
因而分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不仅提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工做用的服务器发生故障,过后均可以用任何一个镜 像出来的本地仓库恢复。由于每一次的提取操做,实际上都是一次对代码仓库的完整备份
更进一步,许多这类系统均可以指定和若干不一样的远端代码仓库进行交互。籍此,你就能够在同一个项目中,分别和不一样工做小组的人相互协做。 你能够根据须要设定不一样的协做流程,好比层次模型式的工做流,而这在之前的集中式系统中是没法实现的。
Git 简史
同生活中的许多伟大事物同样,Git 诞生于一个极富纷争大举创新的年代。
Git --- The stupid content tracker, 傻瓜内容跟踪器。Linus Torvalds 是这样给咱们介绍 Git 的。
Git 是用于 Linux内核开发的版本控制工具。与经常使用的版本控制工具 CVS, Subversion 等不一样,它采用了分布式版本库的方式,没必要服务器端软件支持(wingeddevil注:这得分是用什么样的服务端,使用http协议或者git协议等不太同样。而且在push和pull的时候和服务器端仍是有交互的。),使源代码的发布和交流极其方便。 Git 的速度很快,这对于诸如 Linux kernel 这样的大项目来讲天然很重要。 Git 最为出色的是它的合并跟踪(merge tracing)能力。
实际上内核开发团队决定开始开发和使用 Git 来做为内核开发的版本控制系统的时候,世界开源社群的反对声音很多,最大的理由是 Git 太艰涩难懂,从 Git 的内部工做机制来讲,的确是这样。可是随着开发的深刻,Git 的正常使用都由一些友好的脚本命令来执行,使 Git 变得很是好用,即便是用来管理咱们本身的开发项目,Git 都是一个友好,有力的工具。如今,愈来愈多的著名项目采用 Git 来管理项目开发.
做为开源自由原教旨主义项目,Git 没有对版本库的浏览和修改作任何的权限限制。
Linux 内核开源项目有着为数众广的参与者。 绝大多数的 Linux 内核维护工做都花在了提交补丁和保存归档的繁杂事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。
到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合做关系结束,他们收回了 Linux 内核社区无偿使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linux Torvalds)基于使用 BitKcheper 时的经验教训,开发出本身的版本系统。 他们对新的系统制订了若干目标:
速度
简单的设计
对非线性开发模式的强力支持(容许成千上万个并行开发的分支)
彻底分布式
有能力高效管理相似 Linux 内核同样的超大规模项目(速度和数据量)
自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着使人难以置信的非线性分支管理系统(参见 Git 分支)。
那么,简单地说,Git 到底是怎样的一个系统呢? 请注意接下来的内容很是重要,若你理解了 Git 的思想和基本工做原理,用起来就会知其因此然,游刃有余。 在开始学习 Git 的时候,请努力分清你对其它版本管理系统的已有认识,如 Subversion 和 Perforce 等;这么作能帮助你使用工具时避免发生混淆。 Git 在保存和对待各类信息的时候与其它版本控制系统有很大差别,尽管操做起来的命令形式很是相近,理解这些差别将有助于防止你使用中的困惑。
Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差异在于 Git 对待数据的方法。 概念上来区分,其它大部分系统以文件变动列表的方式存储信息。 这类系统(CVS、Subversion、Perforce、Bazaar 等等)将它们保存的信息看做是一组基本文件和每一个文件随时间逐步累积的差别。
Git 不按照以上方式对待或保存数据。 反之,Git 更像是把数据看做是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的所有文件制做一个快照并保存这个快照的索引。 为了高效,若是文件没有修改,Git 再也不从新存储该文件,而是只保留一个连接指向以前存储的文件。 Git 对待数据更像是一个 快照流。
这是 Git 与几乎全部其它版本控制系统的重要区别。 所以 Git 从新考虑了之前每一代版本控制系统延续下来的诸多方面。 Git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不仅是一个简单的 VCS。 稍后咱们在Git 分支讨论 Git 分支管理时,将探究这种方式对待数据所能得到的益处。
在 Git 中的绝大多数操做都只须要访问本地文件和资源,通常不须要来自网络上其它计算机的信息。 若是你习惯于全部操做都有网络延时开销的集中式版本控制系统,Git 在这方面会让你感到速度之神赐给了 Git 超凡的能量。 由于你在本地磁盘上就有项目的完整历史,因此大部分操做看起来瞬间完成。
举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,而后再显示出来——它只需直接从本地数据库中读取。 你能当即看到项目历史。 若是你想查看当前版本与一个月前的版本之间引入的修改,Git 会查找到一个月前的文件作一次本地的差别计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。
这也意味着你离线或者没有 ××× 时,几乎能够进行任何操做。 如你在飞机或火车上想作些工做,你能愉快地提交,直到有网络链接时再上传。 如你回家后 ××× 客户端不正常,你仍能工做。 使用其它系统,作到如此是不可能或很费力的。 好比,用 Perforce,你没有链接服务器时几乎不能作什么事;用 Subversion 和 CVS,你能修改文件,但不能向数据库提交修改(由于你的本地数据库离线了)。 这看起来不是大问题,可是你可能会惊喜地发现它带来的巨大的不一样。
Git 中全部数据在存储前都计算校验和,而后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程当中丢失信息或损坏文件,Git 就能发现。
Git 用以计算校验和的机制叫作 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:
24b9da6552252987aa493b52f8696cd6d3b00373
Git 中使用这种哈希值的状况不少,你将常常看到这种哈希值。 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
你执行的 Git 操做,几乎只往 Git 数据库中增长数据。 很难让 Git 执行任何不可逆操做,或者让它以任何方式清除数据。 同别的 VCS 同样,未提交更新时有可能丢失或弄乱修改的内容;可是一旦你提交快照到 Git 中,就难以再丢失数据,特别是若是你按期的推送数据库到其它仓库的话。
这使得咱们使用 Git 成为一个安心愉悦的过程,由于咱们深知能够尽情作各类尝试,而没有把事情弄糟的危险。 更深度探讨 Git 如何保存数据及恢复丢失数据的话题,请参考撤消操做。
好,请注意。 若是你但愿后面的学习更顺利,记住下面这些关于 Git 的概念。 Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。 已提交表示数据已经安全的保存在本地数据库中。 已修改表示修改了文件,但还没保存到数据库中。 已暂存表示对一个已修改文件的当前版本作了标记,使之包含在下次提交的快照中。
由此引入 Git 项目的三个工做区域的概念:Git 仓库、工做目录以及暂存区域。
Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
工做目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
暂存区域是一个文件,保存了下次将提交的文件列表信息,通常在 Git 仓库目录中。 有时候也被称做“索引”,不过通常说法仍是叫暂存区域。
对于任何一个文件,在 Git 内都只有三种状态:
中文 | 英文 | 含义 |
已提交 | committed | 已提交表示该文件已经被安全地保存在本地数据库中了 |
已修改 | modified | 已修改表示修改了某个文件,但尚未提交保存 |
已暂存 | staged | 已暂存表示把已修改的文件放在下次提交时要保存的清单中 |
git中还有三类经常使用对象(实际不止三种),理解这三类对象也很重要。分别为:
blob,用于表示一个文件
tree,用于表示一个目录,索引到若干文件或子目录
commit,用于表示一次提交(commit)
全部对象都会以文件的形式保存在.git/objects
目录,一个对象一个文件。
目录 用法
git 目录 它是 Git 用来保存元数据和对象数据库的地方。该目录很是重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
工做目录 从项目中取出某个版本的全部文件和目录,用以开始后续工做的叫作工做目录。这些文件实际上都是从 git 目录中的压缩对象数据库中提取出来的,接下来就能够在工做目录中对这些文件进行编辑
暂存区域 所谓的暂存区域只不过是个简单的文件,通常都放在 git 目录中。有时候人们会把这个文件叫作索引文件,不过标准说法仍是叫暂存区域。
基本的 Git 工做流程以下:
1.在工做目录中修改文件。 2.暂存文件,将文件的快照放入暂存区域。 3.提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
若是 Git 目录中保存着的特定版本文件,就属于已提交状态。 若是做了修改并已放入暂存区域,就属于已暂存状态。 若是自上次取出后,做了修改但尚未放到暂存区域,就是已修改状态。 在Git 基础一章,你会进一步了解这些状态的细节,并学会如何根据文件状态实施后续操做,以及怎样跳过暂存直接提交。
使用Git过程当中,必须经过建立分支进行开发,坚定禁止在主干分支上直接开发。review的同事有责任检查其余同事是否遵循分支规范。
在Git中,默认是不会提交空目录的,若是想提交某个空目录到版本库中,须要在该目录下新建一个 .gitignore 的空白文件,就能够提交了
【代码回溯注意】把外部文件归入到本身的 Git 分支来的时候必定要记得是先比对,确认全部修改都是本身修改的,而后再归入。否则,容易出现代码回溯
【代码回溯注意】多人协做时,不要各自在本身的 Git 分支开发,而后发文件合并。正确的方法应该是开一个远程分支,而后一块儿在远程分支里协做。否则,容易出现代码回溯(即别人的代码被覆盖的状况)
【代码回溯注意】每一个人提交代码是必定要 git diff 看提交的东西是否是都是本身修改的。若是有不是本身修改的内容,极可能就是代码回溯
【代码回溯注意】review 代码的时候若是看到有被删除掉的代码,必定要确实是不是写代码的同事本身删除的。若是不是,极可能就是代码回溯
分支合并及上线
步骤 | Git 操做 |
克隆代码 | git clone 远程代码 |
建立分支 | git checkout -b branch_name |
在分支中开发 | 无 |
review代码 | 无 |
第一轮测试 | 无 |
添加代码到分支的暂存区 | git add somefile |
提交代码到分支 | git commit -m "本次提交的注释" |
切换到主版本 | git checkout master |
获取远程最新代码 | git pull origin master |
合并某分支到master分支 | git merge branch_name |
解决合并时产生的冲突 请参考分支合并时冲突的解决 | 无 |
第二轮测试 | 无 |
准备上线文档 | 无 |
获取远程最新代码 | git pull origin master |
推送master分支 | git push origin master |
通知上线 | 无 |
没有问题了删除本地分支 | git branch -d branch_name |
如下命令为配置 Git 相关信息,如下两项必需要配置,会出如今每次提交的信息里。
git config --global user.name "John" #规定为姓名全拼 git config --global user.email "John@126.com" #规定为公司邮箱 git config --global merge.tool "meld" #可视化的合并工具 git config --global color.ui true # 使用git默认的配色方案,推荐 git config --global --list # 查看配置信息 git config --global user.name # 查看 user.name 的配置信息
Git的功能特性:
从通常开发者的角度来看,git有如下功能:
一、从服务器上克隆完整的Git仓库(包括代码和版本信息)到单机上。 二、在本身的机器上根据不一样的开发目的,建立分支,修改代码。 三、在单机上本身建立的分支上提交代码。 四、在单机上合并分支。 五、把服务器上最新版的代码fetch下来,而后跟本身的主分支合并。 六、生成补丁(patch),把补丁发送给主开发者。 七、看主开发者的反馈,若是主开发者发现两个通常开发者之间有冲突(他们之间能够合做解决的冲突),就会要求他们先解决冲突,而后再由其中一我的提交。若是主开发者能够本身解决,或者没有冲突,就经过。 八、通常开发者之间解决冲突的方法,开发者之间可使用pull 命令解决冲突,解决完冲突以后再向主开发者提交补丁。
从主开发者的角度(假设主开发者不用开发代码)看,git有如下功能:
一、查看邮件或者经过其它方式查看通常开发者的提交状态。 二、打上补丁,解决冲突(能够本身解决,也能够要求开发者之间解决之后再从新提交,若是是开源项目,还要决定哪些补丁有用,哪些不用)。 三、向公共服务器提交结果,而后通知全部开发人员。
优势:
适合分布式开发,强调个体。
公共服务器压力和数据量都不会太大。
速度快、灵活。
任意两个开发者之间能够很容易的解决冲突。
离线工做。
缺点:
资料少(起码中文资料不多)。
学习周期相对而言比较长。
不符合常规思惟。
代码保密性差,一旦开发者把整个库克隆下来就能够彻底公开全部代码和版本信息。
依赖库:
yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel asciidoc xmlto docbook2x perl-ExtUtils-Embed texinfo yum install -y tk zlib-devel openssl-devel perl cpio expat-devel gettext-devel asciidoc xmlto openjade perl-XML-SAX
docbook2x 这个库须要额外安装
wget ftp://ftp.is.co.za/mirror/fedora.redhat.com/epel/6/x86_64/docbook2X-0.8.8-1.el6.x86_64.rpm rpm -ivh docbook2X-0.8.8-1.el6.x86_64.rpm ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
当你安装好全部的必要依赖,你能够继续从几个地方来取得最新发布版本的 tar 包。 你能够从 Kernel.org 网站获取,网址为 https://www.kernel.org/pub/software/scm/git, GitHub 网站上的镜像来得到,网址为 https://github.com/git/git/releases。 一般在 GitHub 上的是最新版本,但 kernel.org 上包含有文件下载签名,若是你想验证下载正确性的话会用到。
编译安装:
wget https://www.kernel.org/pub/software/scm/git/git-2.10.2.tar.gz --no-check-certificate tar -zxvf git-2.10.2.tar.gz cd git-2.10.2 make clean 若是时间长,出现warning,多是系统时间问题 [root@John git-2.10.2]# make configure GIT_VERSION = 2.10.2 GEN configure ./configure --prefix=/usr make all doc info make install install-doc install-html install-info
建立新仓库 获取与建立项目 你得先有一个 Git 仓库,才能用它进行操做。仓库是 Git 存放你要保存的快照的数据的地方。 拥有一个 Git 仓库的途径有两种。在已有的目录中,初始化一个新的, 其一。 好比一个新的项目,或者一个已存在的项目,但该项目还没有有版本控制。 若是你想要复制一份别人的项目, 或者与别人合做某个项目,也能够从一个公开的 Git 仓库克隆, 其二。本章将对二者都作介绍。 建立新文件夹,打开,而后执行 git init 以建立新的 git 仓库。
[root@John /]# ls -a . .autofsck bin cgroup etc home lib64 media mnt opt root selinux sys usr www .. .autorelabel boot dev .git lib lost+found misc net proc sbin srv tmp var [root@John /]# cd .git/ [root@John .git]# ls branches config description HEAD hooks info objects refs
该目录下可能还会包含其余文件,不过对于一个全新的 git init 版本库,这将是你看到的默认结构。 description 文件仅供 GitWeb 程序使用,咱们无需关心。 config 文件包含项目特有的配置选项。 info 目录包含一个全局性排除(global exclude)文件, 用以放置那些不但愿被记录在 .gitignore 文件中的忽略模式(ignored patterns)。 hooks 目录包含客户端或服务端的钩子脚本(hook scripts), 在 Git 钩子 中这部分话题已被详细探讨过。 剩下的四个条目很重要: HEAD 文件、(尚待建立的)index 文件,和 objects 目录、refs 目录。 这些条目是 Git 的核心组成部分。 objects 目录存储全部数据内容; refs 目录存储指向数据(分支)的提交对象的指针; HEAD 文件指示目前被检出的分支; index 文件保存暂存区信息。 咱们将详细地逐一检视这四部分,以期理解 Git 是如何运转的。 恭喜,如今你就有了一个 Git 仓库的架子,能够开始快照你的项目了。 简而言之,用 git init 来在目录中建立新的 Git 仓库。 你能够在任什么时候候、任何目录中这么作,彻底是本地化的。
用户信息:
当安装完 Git 应该作的第一件事就是设置你的用户名称与邮件地址。
这样作很重要,由于每个 Git 的提交都会使用这些信息,而且它会写入到你的每一次提交中,不可更改:
[root@John git-2.10.2]# git config --global user.name 'John Doe' [root@John git-2.10.2]# git config --global user.email XXOO@126.com
再次强调,若是使用了 --global 选项,那么该命令只须要运行一次,由于以后不管你在该系统上作任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不一样的用户名称与邮件地址时,能够在那个项目目录下运行没有 --global 选项的命令来配置。
不少 GUI 工具都会在第一次运行时帮助你配置这些信息。
获取帮助
若你使用 Git 时须要获取帮助,有三种方法能够找到 Git 命令的使用手册:
$ git help <verb> $ git <verb> --help $ man git-<verb>
例如,要想得到 config 命令的手册,执行
$ git help config
这些命令很棒,由于你随时随地可使用而无需联网。
若是你以为手册或者本书的内容还不够用,你能够尝试在 Freenode IRC 服务器( irc.freenode.net )的 #git 或 #github 频道寻求帮助。
这些频道常常有上百人在线,他们都精通 Git 而且乐于助人。
总结
你应该已经对 Git 是什么、Git 与你可能正在使用的集中式版本控制系统有何区别等问题有了基本的了解。
如今,在你的我的系统中应该也有了一份可以工做的 Git 版本。
是时候开始学习有关 Git 的基础知识了。
上面的四条命令在工做目录、暂存目录(也叫作索引)和仓库之间复制文件。
git add files
把当前文件放入暂存区域。
git commit
给暂存区域生成快照并提交。
git reset -- files
用来撤销最后一次git add files
,你也能够用git reset
撤销全部暂存区域文件。
git checkout -- files
把文件从暂存区域复制到工做目录,用来丢弃本地修改。
你能够用 git reset -p
, git checkout -p
, or git add -p
进入交互模式。
也能够跳过暂存区域直接从仓库取出文件或者直接提交代码。
git commit -a
至关于运行 git add 把全部当前目录下的文件加入暂存区域再运行。git commit.
git commit files
进行一次包含最后一次提交加上工做目录中文件快照的提交。而且文件被添加到暂存区域。
git checkout HEAD -- files
回滚到复制最后一次提交。
git基本命令:
设置用户名:git config --global user.name"your name" 设置Email:git config --global user.email"email name" 建立目录:mkdir name 退回目录:cd name 显示当前目录:pwd 把目录变成git可管理的仓库:git init 添加文件到仓库:git add 文件名 提交文件到仓库:git commit 掌握仓库当前的状态:git status 查看具体修改内容:git diff 查看历史记录:git log 回退版本:git reset --hard HEAD^ 恢复回退的版本:git reset --hard 版本号 记录每一次记录:git reflog 把readme.txt文件在工做区的修改所有撤销:git checkout --文件名 删除一个文件:git rm 文件名 版本库里的版本替换工做区的版本:git checkout -- 文件名 建立SSH key:ssh-keygen -t rsa -C "邮箱名称" 本地关联远程数据库:git remote add origin git@git.oschina.net:John.com/testGit.git git@git.oschina.net:John/newFile.git git@git.oschina.net:John/helloWord.git 将本地数据推送到远程仓库中:git push -u origin master(注意本地仓库名称必定跟远程仓库名称相同) 将远程仓库中的数据下载到本地仓库:git clone git@git.oschina.net:John.com/gitSkills.git 建立并切换分支:git checkout -b 分支名称 查询全部分支:git branch 切换分支:git checkout 分支名称 合并指定分支到当前分支:git merge dev 删除分支:git branch -d 分支名称 合并分支:git merge 分支名称 合并分支禁用Fast forward:git merger --no-ff -m "注释" dev 把当前现场“储存起来”:git stash 查看工做现场列表:git stash list 恢复现场:1 git stash apply stash内容并不删除,你须要用git stash drop来删除; 2 git stash pop 恢复的同时把stash内容也删了 强行删除分支:git branch -D 分支名 将分支推送到远程仓库的对应分支上:git push origin 分支名称 抓取最新的提交从远程仓库中:git pull 创建本地分支和远程分支的关联:git branch --set-upstream dev origin/dev 在本地建立和远程分支对应的分支:git checkout -b branch-名字 origin/branch-名字 建立标签:git tag 标签名 查看标签:git tag 对指定的commit打标签:git tag commitId 建立带说明的标签:git tag -a 标签名 -m "说明" commit的ID 删除标签:git tag -d 标签名 推送标签名到远程:git push origin 标签名 一次性推送全部的标签名:git push origin --tags 从远程仓库删除标签:gitpush origin :refs/tags/标签名 为命令配置别名:git config --global alias.st status
git总结:
注意事项: #1. 多提交(至关于多保存,多^S): 在Git中任何已提交的东西几乎老是能够恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也能够恢复。 然而,任何你未提交的东西丢失后极可能再也找不到了。 #2. 拉取别人数据以前要提交。减小工做区,暂存区数据冲突的可能。 #3. 推送以前先拉取。即将自已的版本作为最新以前,要先合并别人的修改。 #4. 切换分支前要提交,不然有可能数据丢失。即保存在此分支的修改。 #5. 合并分支以前要提交。拉取视状况而定(建议拉取)。 #6. 慎用 git checkout -- <file> 撤消对文件的修改(拷贝了另外一个文件来覆盖它), 除非你确实清楚不想要那个文件了,不然不要使用这个命令。 #7. 尝试让每个提交成为一个逻辑上的独立变动集。一个问题一个提交,这个提交包含了这个问题的所有修改。 #8. 最后一件要牢记的事是提交信息。 有一个建立优质提交信息的习惯会使 Git 的使用与协做容易的多。 #9. 变基:只对还没有推送或分享给别人的本地修改执行变基操做清理历史,从不对已推送至别处的提交执行变基操做。 #10. SourceTree GitFlow快捷键(mac):alt + 花 + F 异常惊艳 环境搭建 #1:安装 Mac: Mac苹果系统: git2.10.1 + sourceTree2.3.2 Win: Windows 64 bit: git2.5.1 + TortoiseGit + zh #2:配置用户信息 Win: 设置 ---> Git Mac: sourcetree ---> 偏好设置 ----> 通用 #3: 配置密钥 Win: ???? Mac: $ ssh -keygen -t rsa -C youremail@example.com (一路yes或null就能够) 会存储在:/Users/mac/.ssh/*.pub #4: 避免每次输入密码(未验证) git config --global credential.helper cache #5:仓库划分和SVN相同。 Art:加工 3dMax, ps的资源成为unity使用的 *.ab Design: 提供服务器和客户端用的表 Public.ResPackage: 存Art生成的资源 Public.PackedVersionConfig: 制作和存储version.txt文件及热更新文件 Public.TTDS_apk:存安装包 Server:服务器 Client:客户端 #6: Clone工程 a. 建立目标目录 b. Win: ---- Mac: git clone client@10.1.10.100:tiantiandiansha.git c. 显示隐藏文件 + 把(.git + 其它调整到合适位置) d. 用工具打开:菜单---> 仓库---> git flow ---> 初使化仓库 确认本工程在 Develop分支 分支 #1: 分支的划分和目的(git flow) a. 线上问题 master[主干]: 备份线上版本。 hotfix[临时]: 修复线上bug。 b. 平常开发 develop[主干]: 功能集成。 features[临时]: 平常开发。 c. 发布 master[主干]: 根据Tag发布版本。 release[临时]: develop某些功能达到可发布程度,建立此分支,把功能集成到master,加Tag以备发版打包。 #2:在哪一个分支上High a. 具体操作都在分支中完成,主干只负责数据集成。减小冲突方便并行。 把主干当作单纯的数据源,分支是一个独立的空间。一个操作能够表述为,为达到一个目的从某个数据源取得数据、建立空间;而后在这个独立的空间里对其进行处理;处理完成以后再更新到某些数据源。一个操作结束。此分支也完成了他的使命。 b. features:平常功能开发 + develop上的bug修复。 c. hotfix: 线上bug修复。 在master主干根据Tag建立,完成以后是否合并到develop或master须要根据develp或master的后续版本是否已修改来定。未修改的须要合并到develop+master。已修改的能够直接在hotfix分支打包发布。另外是否合并还要考虑是不是临时性暴力修复。 注意:hotfix分支是从master旧的版本建立来的,合并时请注意莫回档。 d. release:目的是把develop成熟的功能合并到master并打Tag。供后面按需发布。不在release分支作bug修复。 e. bug修复: develop主干bug:由features分支修复。 master线上bug:由hotfix分支修复。 master未上线bug:由release 或 features + release修复(只果只用features须要手动将分支合并到master)。 #3:分支切换 a. 未跟踪的文件:显示在了工做区。因未归入任何分支,因此全部分支均可填加。 在目标分区提交了原分区未暂存的文件,切换回原分支,原未暂存文件丢失。 b. 已暂存未提交(新增长的文件,开始跟踪): 不放弃本地变动,到目标分支时还在已暂存未提交状态(sourceTree功能,将原分支的暂存状态copy过来了)。 放弃本地变动,目标分支不存在已暂存未提交文件。再切回原分支原已暂存未提交文件丢失。(放弃本地变动==放弃填加文件) 已暂存未提交(提交后再次修改): 不放弃本地变动, sourTree不容许。提示,先提交或隐藏(stash),以后再切换。 放弃本地变动,目标分支不存在已暂存未提交文件。再切回原分支,原已暂存的修改丢失。(放弃本地变动==放弃已暂存文件修改) 说明:切换分支时,将丢弃原分支已暂存的修改。 c. 已提交的文件:原分支已提交的文件不会带入新的分支。 请牢记:当你切换分支的时候,Git 会重置你的工做目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会自动添加、删除、修改文件以确保此时你的工做目录和这个分支最后一次提交时的样子如出一辙。 总结:切换分支时,应保存(提交或隐藏)本分支的操做。不然切换回来后,未保存的内容将丢失。 由于当前工做区和暂存区只有一份,切换分支时要清除属于原分支的内容。未跟踪或首次暂存内容可进入新分支是工具的优化。 #4: 分支合并 什么时候会合并: a. 用git pull从远端拉取时会合并(git pull = git fetch + git merge)。 b. 主动合并分支时:如git flow的 features release 完成时。 合并方法: 在 Git 中整合来自不一样分支的修改主要有两种方法:merge 以及 rebase(变基) a. 未分叉状况:快进方式(fast-forward) 因为当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,因此 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,若是顺着一个分支走下去可以到达另外一个分支,那么 Git 在合并二者的时候,只会简单的将指针向前推动(指针右移),由于这种状况下的合并操做没有须要解决的分歧——这就叫作 “快进(fast-forward)” b. 分叉状况: 在这种状况下,你的开发历史从一个更早的地方开始分叉开来(diverged)。 由于,master 分支所在提交并非 iss53 分支所在提交的直接祖先,Git 不得不作一些额外的工做。 出现这种状况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的工做祖先(C2),作一个简单的三方合并。 和之间将分支指针向前推动所不一样的是,Git 将这次三方合并的结果作了一个新的快照而且自动建立一个新的提交指向它。 这个被称做一次合并提交,它的特别之处在于他有不止一个父提交。 冲突: a. 只有合并时才会有冲突。 b. 文件冲突时,Git已经完成了合并(有冲突标记,此时冲突的文件应是已修改未暂存状态),可是没有自动地建立一个新的合并提交。此时Git会暂停下来,等待你去解决合并产生的冲突。 在你解决了全部文件里的冲突以后,对每一个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些本来有冲突的文件,Git 就会将它们标记为冲突已解决。 变基: a. 原理: 它的原理是首先找到这两个分支(即当前分支 experiment、变基操做的目标基底分支 master)的最近共同祖先 C2,而后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,而后将当前分支指向目标基底 C3, 最后以此将以前另存为临时文件的修改依序应用。 这两种整合方法(merge和rebase)的最终结果没有任何区别,可是变基使得提交历史更加整洁。 b. 风险: 变基也并不是天衣无缝,要用它得遵照一条准则:不要对在你的仓库外有副本的分支执行变基。 总的原则是,只对还没有推送或分享给别人的本地修改执行变基操做清理历史,从不对已推送至别处的提交执行变基操做,这样,你才能享受到两种方式带来的便利。 发版相关 a. 使用 master分支发版(旧版本 + 新版本),因此需将开发分支(develop)的修改合并到master。 b. 哪一个仓库需合并到master: Art: ??(负责生成 AssesBundle的人?) Design: ?? Server: 客户端发版的人 Client:服务器发版的人 Public: 客户端发版的人 或 制作热更新包的人 c. 合并到master分支的时间: Art: 成功发版后和加Tag一块儿 Design: 成功发版后和加Tag一块儿 Public: 成功发版后和加Tag一块儿 Server: 发版结点,开发分支测试经过后。 Client:发版结点,开发分支测试经过后。 d. 加Tag: 成功发版后给master分支加Tag. 以备之后切换到此Tag当时的版本改bug或发版本。 由合并到master的人加Tag. 注意:为保证根据Tag找到全部数据,tag不能漏加,tag格式一致(至少含相同版本号,精确到资源版本号 1.0.38.0.0 )。 基础: 详情请参考:https://git-scm.com/book/zh/v2 #1. 文件状态及对应的工做区 Git状态:已修改(modified),已暂存(staged),已提交(committed)----- 只管理已跟踪文件 工做区: 工做目录, 暂存区, Git仓库 文件状态:未跟踪 已跟踪(未修改,已修改,已暂存) 未跟踪:新加入当前分支,从未暂存(git add)过的文件。 已跟踪:已提交到Git仓库或暂存过的文件 已跟踪已暂存:暂存区中的文件(git add过)。 已跟踪已修改:工做区中的文件。 已跟踪未修改:已提交到Git仓库的文件(git commit过)。 #2. 暂存: 1. 暂存操做会为每个文件计算校验和(使用SHA-1哈希算法) 2. 而后会把当前版本的文件快照保存到Git仓库中(Git使用blob对象来保存它们) 3. 最终将校验和加入到暂存区域等待提交。 #3. 提交: 1. 建立树对象并保存到Git仓库: Git会先计算当前分支的每个子目录的校验和,而后在Git仓库中将这些校验和保存为树对象。 2. 建立提交对象并保存到Git仓库: 随后,Git便会建立一个提交对象(commit object)。提交对象保存的内容: a. 包含了做者的姓名和邮箱、提交时输入的信息。 b. 指向它的父对象的指针。(首次提交产生的提交对象没有父对象,普通提交有一个父对象,而由多个分支合并产生的提交对象有多个父对象) c. 还包含指向1建立的树对象(项目根目录)的指针。 3. 注意:提交只提交暂存区中的文件(修改过但未暂存的文件不会被提交)。 暂存提交以后:Git 仓库中有五个对象: a. 三个 blob 对象(暂存时保存的文件快照) b. 一个树对象(记录着目录结构和 blob 对象索引) c. 以及一个提交对象(包含着指向前述树对象的指针和全部提交信息)。 #4. 分支 a. Git的分支,其实本质上仅仅是指向提交对象的可变指针(Tag是不变的指针)。 b. HEAD: 在 Git 中,它是一个指针,指向当前所在的本地分支(译注:将 HEAD 想象为当前分支的别名)。 https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%AE%80%E4%BB%8B [我的理解]: 拉取,抓取,推送,都是对提交对象的下载上传,分支进度就是改变分支指针指向不一样的对象。 #5. 抓取:git fetch [remote-name] git fetch: 命令与一个远程的仓库交互,而且将远程仓库中有可是在当前仓库的没有的全部信息拉取下来而后存储在你本地数据库中。 https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E7%9A%84%E4%BD%BF%E7%94%A8#_fetching_and_pulling #6. 拉取: a. git pull: 命令基本上就是 git fetch 和 git merge 命令的组合体。 b. 完整格式:git pull <远程主机名> <远程分支名>:<本地分支名> b. git pull : Git从你指定的(当前分支所跟踪的)远程仓库中抓取内容,而后立刻尝试将其合并进你所在的分支中。 http://www.yiibai.com/git/git_pull.html #7. 推送:git push [remote-name] [branch-name] a. git push: 计算你本地数据库与远程仓库的差别,而后将差别推送到另外一个仓库中。 它须要有另外一个仓库的写权限 #8. .git 目录 这些条目是 Git 的核心组成部分。 objects: 目录存储全部数据内容; refs: 目录存储指向数据(分支)的提交对象的指针; HEAD: 文件指示目前被检出的分支; index: 文件保存暂存区信息。 命令 详情请参考:https://git-scm.com/book/zh/v2 http://www.yiibai.com/git/git_pull.html git help git init git status a. Untracked files: 未跟踪的文件 b. Changes to be committed: (说明是已暂存状态) (use "git reset HEAD <file>..." to unstage) c. Changes not staged for commit: (说明已跟踪文件的内容发生了变化,但尚未放到暂存区) (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) d. You have unmerged paths.(合并冲突) (fix conflicts and run "git commit") e. All conflicts fixed but you are still merging. (use "git commit" to conclude merge) git status -s ??: 新添加的未跟踪文件前面有 ?? 标记 A : 新添加到暂存区中的文件前面有 A 标记 MM: 修改过的文件前面有 M 标记。 左M: 修改了并放入了暂存区 右M: 修改了还没放入暂存区. 两位:左表暂存区,右表工做区 说明:-s 不显示需推送的内容,只涉及到工做区和暂存区,Git仓库的状态不显示。 git add <文件|目录> : (添加内容到下一次提交中) a. 开始跟踪新文件 b. 把已跟踪(已修改)的文件放到暂存区 c. 合并时把有冲突的文件标记为已解决状态等 运行了 git add 以后又做了修订的文件,须要从新运行 git add 把最新版本从新暂存起来: git reset HEAD <file> 说明:取消暂存的文件 NOTE: 虽然在调用时加上 --hard 选项能够令 git reset 成为一个危险的命令(译注:可能致使工做目录中全部当前进度丢失!),但本例中工做目录内的文件并不会被修改。 不加选项地调用 git reset 并不危险 — 它只会修改暂存区域。 git checkout -- <file> 说明:撤消对文件的修改(拷贝了另外一个文件来覆盖它) IMPORTANT:这是一个危险的命令。 你对那个文件作的任何修改都会消失。除非你确实清楚不想要那个文件了,不然不要使用这个命令。 git diff 此命令比较的是工做目录中当前文件和暂存区域快照之间的差别, 也就是修改以后尚未暂存起来的变化内容。 请注意,git diff 自己只显示还没有暂存的改动,而不是自上次提交以来所作的全部改动。 因此有时候你一会儿暂存了全部更新过的文件后,运行 git diff 后却什么也没有,就是这个缘由。 git diff --staged(等同于 git diff --cached) 查看已暂存的将要添加到下次提交里的内容。是暂存文件和已提交文件的比较。 git commit (这种方式会启动文本编辑器以便输入本次提交的说明) git commit -m "Story 182: Fix benchmarks for speed" 请记住,提交时记录的是放在暂存区域的快照。 任何还未暂存的仍然保持已修改状态,能够在下次提交时归入版本管理。 每一次运行提交操做,都是对你项目做一次快照,之后能够回到这个状态,或者进行比较。 git commit -a -m 'added new benchmarks' (git acm: git add + git commit -m) git commit --amend commit以后:版本修改将添加到历史记录 git rm PROJECTS.md(等于 git rm -f PROJECTS.md) git rm --cached PROJECTS.md git rm -f PROJECTS.md 目标文件未被跟踪:操作无效 目标文件在暂存区: a. 无参:提示加参数 --cached 或 -f b. -f: 从暂存区中删除,也从本地文件系统中删除。 c. --cached: 从暂存区中删除,但不从本地文件系统删除。 目标文件已提交在Git仓库中: a. 无参或加-f参数:即从仓库中删除,也从本地文件系统中删除。 b. --cached: 从仓库中删除,但不从本地文件系统删除。 git mv file_from file_to 运行 git mv 就至关于运行了下面三条命令: $ mv README.md README $ git rm README.md $ git add README git log -p -2 git log --pretty=oneline git log --pretty=format:"%h - %an, %ar : %s" git log --pretty=format:"%h %s" --graph git log --since=2.weeks git log -Sfunction_name git log --pretty="%h - %s" --graph -- 1.txt git log --oneline --decorate 查看各个分支当前所指的对象 git clone https://github.com/schacon/ticgit git clone git@github.com:mojombo/grit.git NewName git remote git remote -v git remote show [remote-name] 查看远程仓库 git remote add <shortname> <url> 添加远程仓库 git remote rm paul 远程仓库的移除 git remote rename pb paul 远程仓库的重命名 git fetch [remote-name] 从远程仓库中抓取与拉取 a. 这个命令查找 “origin” 是哪个服务器(在本例中,它是 git.ourcompany.com), 从中抓取本地没有的数据, b. 而且更新本地数据库. c. 移动 origin/master 指针指向新的、更新后的位置。 当 git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工做目录中的内容。 它只会获取数据而后让你本身合并。 要特别注意的一点是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)。 换一句话说,这种状况下,不会有一个新的 serverfix 分支 - 只有一个不能够修改的 origin/serverfix 指针。 能够运行 git merge origin/serverfix 将这些工做合并到当前所在的分支。 若是想要在本身的 serverfix 分支上工做,能够将其创建在远程跟踪分支之上 git push [remote-name] [branch-name] 当你和其余人在同一时间克隆,他们先推送到上游而后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工做拉取下来并将其合并进你的工做后才能推送。 阅读 Git 分支 了解如何推送到远程仓库服务器的详细信息。 git tag git tag -l 'v1.8.5*' git tag -a v1.4 -m 'my version 1.4' 附注标签 git tag -a v1.2 9fceb02 后期打标签 git tag v1.4 轻量标签 git show v1.4 git push origin v1.5 共享标签 git push origin --tags git push origin --delete serverfix 删除一个远程分支 基本上这个命令作的只是从服务器上移除这个指针。 Git 服务器一般会保留数据一段时间直到垃圾回收运行,因此若是不当心删除掉了,一般是很容易恢复的。 git checkout -b version2 v2.0.0 在 Git 中你并不能真的检出一个标签,由于它们并不能像分支同样来回移动。 若是你想要工做目录与仓库中特定的标签版本彻底同样,可使用 git checkout -b [branchname] [tagname] 在特定的标签上建立一个新分支: git checkout -b [branch] [remotename]/[branch] git checkout --track origin/serverfix git checkout -b sf origin/serverfix git branch -u origin/serverfix 设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支,你能够在任意时间使用 -u 或 --set-upstream-to 选项运行 git branch 来显式地设置。 git branch git branch -v 查看每个分支的最后一次提交 git branch -vv 查看设置的全部跟踪分支,可使用 git branch 的 -vv 选项 须要重点注意的一点是这些数字的值来自于你从每一个服务器上最后一次抓取的数据。 这个命令并无链接服务器,它只会告诉你关于本地缓存的服务器数据。 若是想要统计最新的领先与落后数字,须要在运行此命令前抓取全部的远程仓库。 能够像这样作:$ git fetch --all; git branch -vv git branch --merged git branch --no-merged git branch testing git branch -d iss53 git checkout testing git checkout -b iss53 git pull a. 在大多数状况下它的含义是一个 git fetch 紧接着一个 git merge 命令。 b. 无论它是显式地设置仍是经过 clone 或 checkout 命令为你建立的,git pull 都会查找当前分支所跟踪的服务器与分支,从服务器上抓取数据而后尝试合并入那个远程分支。 git pull <远程主机名> <远程分支名>:<本地分支名> git merge iss53 git rebase master git gc 最妙之处是你能够随时从新打包。 Git 时常会自动对仓库进行从新打包以节省空间。固然你也能够随时手动执行 git gc 命令来这么作。 当版本库中有太多的松散对象,或者你手动执行 git gc 命令,或者你向远程服务器执行推送时,Git 都会这样作。
HEAD: 表示最近一次的 commit。 MERGE_HEAD: 若是是 merge 产生的 commit,那么它表示除 HEAD 以外的另外一个父母分支。 FETCH_HEAD: 使用 git-fetch 得到的 object 和 ref 的信息都存储在这里,这些信息是为往后 git-merge 准备的。 HEAD^: 表示 HEAD 父母的信息 HEAD^^: 表示 HEAD 父母的父母的信息 HEAD~4: 表示 HEAD 上溯四代的信息 HEAD^1: 表示 HEAD 的第一个父母的信息 HEAD^2: 表示 HEAD 的第二个父母的信息 COMMIT_EDITMSG: 最后一次 commit 时的提交信息。