git基础

Git基本工作原理

参考https://gitee.com/progit/

想知道Git是一个怎样的系统需要理解了Git的基本工作原理,这样用起来就会知其所以然,游刃有余。在开始学习Git的时候,不要尝试把各种概念和其他版本控制系统(如Subversion等)相比拟,否则容易混淆每个操作的实际意义。Git在保存和处理各种信息的时候,虽然操作起来的命令形式非常相近,但它与其他版本控制系统的做法颇为不同。理解这些差异将有助于你准确地使用Git提供的各种工具。

直接记录快照,而非差异比较

Git和其他版本控制系统的主要差别在于,Git只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异,这类系统(CVS,Subversion,Perforce,Bazaar等等)每次记录有哪些文件作了更新,以及都更新了哪些行的什么内容。其他系统在每个版本中记录着各个文件的具体差异

Git并不保存这些前后变化的差异数据。实际上,Git更像是把变化的文件作快照后,记录在一个微型的文件系统中。每次提交更新时,它会纵览一遍所有文件的指纹信息并对文件作一快照,然后保存一个指向这次快照的索引。为提高性能,若文件没有变化,Git不会再次保存,而只对上次保存的快照作一链接。
Git保存每次更新时的文件快照
这是Git同其他系统的重要区别。它完全颠覆了传统版本控制的套路,并对各个环节的实现方式作了新的设计。Git更像是个小型的文件系统,但它同时还提供了许多以此为基础的超强工具,而不只是一个简单的VCS。稍后在第三章讨论Git分支管理的时候,我们会再看看这样的设计究竟会带来哪些好处。

近乎所有操作都是本地执行

在Git中的绝大多数操作都只需要访问本地文件和资源,不用连网。但如果用CVCS的话,差不多所有操作都需要连接网络。因为Git在本地磁盘上就保存着所有当前项目的历史更新,所以处理起来速度飞快。
举个例子,如果要浏览项目的历史更新摘要,Git不用跑到外面的服务器上去取数据回来,而直接从本地数据库读取后展示给你看。所以任何时候都可以马上翻阅,无需等待。如果想要看当前版本的文件和一个月前的版本之间有何差异,Git会取出一个月前的快照和当前文件作一次差异运算,而不用请求远程服务器来做这件事,或是把老版本的文件拉到本地来作比较。
用CVCS的话,没有网络或者断开VPN你就无法做任何事情。但用Git的话,就算你在飞机或者火车上,都可以非常愉快地频繁提交更新,等到了有网络的时候再上传到远程仓库。同样,在回家的路上,不用连接VPN你也可以继续工作。换作其他版本控制系统,这么做几乎不可能,抑或非常麻烦。比如Perforce,如果不连到服务器,几乎什么都做不了(译注:默认无法发出命令p4 edit file开始编辑文件,因为Perforce需要联网通知系统声明该文件正在被谁修订。但实际上手工修改文件权限可以绕过这个限制,只是完成后还是无法提交更新。);如果是Subversion或CVS,虽然可以编辑文件,但无法提交更新,因为数据库在网络上。看上去好像这些都不是什么大问题,但实际体验过之后,你就会惊喜地发现,这其实是会带来很大不同的。

时刻保持数据完整性

在保存到Git之前,所有数据都要进行内容的校验和(checksum)计算,并将此结果作为数据的唯一标识和索引。换句话说,不可能在你修改了文件或目录之后,Git一无所知。所以如果文件在传输时变得不完整,或者磁盘损坏导致文件数据缺失,Git都能立即察觉。
Git使用SHA-1计算数据的校验和,通过对文件的内容或目录的结构计算出一个SHA-1哈希值,作为指纹字符串。该字串由40个十六进制字符(0-9及a-f)组成,如:

Git的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在Git数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。

多数操作仅添加数据

常用的Git操作大多仅仅是把数据添加到数据库。因为任何一种不可逆的操作,比如删除数据,都会使回退或重现历史版本变得困难重重。在别的VCS中,若还未提交更新,就有可能丢失或者混淆一些修改的内容,但在Git里,一旦提交快照之后就完全不用担心丢失数据,特别是养成定期推送到其他仓库的习惯的话。

文件的三种状态

对于任何一个文件,在Git内都只有三种状态:

已提交(committed): 表示该文件已经被安全地保存在本地数据库中了。
已修改(modified): 表示修改了某个文件,但还没有提交保存。
已暂存(staged): 表示把已修改的文件放在下次提交时要保存的清单中。

Git管理项目时,文件流转的三个工作区域:Git的工作目录,暂存区域,以及本地仓库。
工作目录,暂存区域,以及本地仓库

每个项目都有一个Git目录(注:如果git clone出来的话,就是其中.git的目录;如果git clone --bare的话,新建的目录本身就是Git目录。),它是Git用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。这些文件实际上都是从Git目录中的压缩对象数据库中提取出来的,接下来就可以在工作目录中对这些文件进行编辑。
所谓的暂存区域只不过是个简单的文件,一般都放在Git目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。

基本的Git工作流程如下:

在工作目录中修改某些文件。
对修改后的文件进行快照,然后保存到暂存区域。
提交更新,将保存在暂存区域的文件快照永久转储到Git目录中。

所以,我们可以从文件所处的位置来判断状态:如果是Git目录中保存着的特定版本文件,就属于已提交状态;如果作了修改并已放入暂存区域,就属于已暂存状态;如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。

Git常用命令

建立本地仓库

git init:在当前目录新建一个Git仓库
git init <project-name>:新建一个目录,将其初始化为Git代码库
git clone [-b <branch-name>] <url>:克隆一个项目和它的整个历史

Git配置

#--global: 修改~/.gitconfig, --system: 修改/etc/gitconfig, 不带则修改项目根目录的.git/config
git config [--global|--system] user.name "<name>":设置用户提交时用户名字
git config [--global|--system] user.email "<email address>" :设置用户提交时用户邮件地址

增加/删除文件到暂存区

git add <file|directory|.>:添加文件或目录(包含子目录)或当前目录下所有文件到暂存区
git add -p <file>:对于同一个文件的多处变化,可以实现分次提交
git rm [-r] [-f] <file|directory>:删除工作区文件或目录,并且将这次删除放入暂存区
git rm --cached [-r] <file|directory>:停止追踪指定文件,但该文件会保留在工作区
git mv <file1|dir1> <file2|dir2>:修改文件或目录名字,并将修改加入暂存区

暂存区提交

git commit [-a] -m "<commit message>":提交暂存区到本地仓库
git commit --amend [-a|file] -m "<commit message>":重新提交上一次更新,若暂存区有修改,则会一起提交

分支管理

git branch [-a|-r] [-v] [-vv]:列出所有分支
git branch [-t] [--set-upstream|--unset-upstream] <branch name> [remote-branch-name]:新建一个分支,但依然停留在当前分支,可输入跟踪的远程分支
git checkout -b <branch-name> [remote-branch-name]:新建一个分支,且切换到指定分支,可输入跟踪的远程分支
git checkout <branch-name|->:切换到指定分支或者切换到上一分支
git merge <branch-name>:合并指定分支
git branch <-d|-D> <branch-name>:删除指定分支
git push origin --delete <remote-branch-name>:删除指定远程分支

标签管理

git tag:列出所有标签
git tag <tag-name> [commit] [-m "<message>"]:在当前commit或指定的commit中新建一个tag
git tag -d <tag-name>:删除指定tag
git push <remote-name> <tag-name>:推送指定tag到远程仓库
git checkout -b <branch-name> <tag-name>:新建一个分支,指向某个tag

查看信息

git status:显示有变更的文件
git log:显示当前分支的历史版本
	--stat:显示每次提交发生变更的文件
	-S <keyword>:根据关键词搜索提交历史
	--pretty=[<format>]:详情查看2.3小节
	-p <file>:查看指定文件每一次更新的内容
git shortlog -sn:查看所有提交过的用户,按提交次数排序
git blame <file>:显示指定文件修改信息
git diff [file]:显示暂存区和工作区的差异
	--cached [file]:显示暂存区和上一次提交的差异
	HEAD:显示工作区也当前分支最新提交之间的差异
	<commit1> <commit2>:显示两次提交之间的差异
git show <commit>:显示某次提交的元数据和内容变化
	--name-only <commit>:显示某次提交发生变化的文件
	<commit>:<file>:显示某次提交某个文件修改的内容
git reflog:显示当前分支最近几次提交

同步远程仓库

git fetch <remote-name>:下载远程仓库所有变动
git remote -v:显示所有远程仓库
git remote add <remote-name> <url>:增加一个新的远程仓库并命名
git remote show <local-remote-name>:显示远程仓库的信息
git pull <remote-name> <branch>:拉取远程仓库的变化并与本地合并
git push [--force] [--all] <remote-name> <branch>:<remote-branch>:上传本地分支到远程仓库

撤销

git checkout <file|.>:恢复暂存区的指定文件或所有文件到工作区
git checkout <commit> <file>:恢复某个已提交的指定文件到暂存区和工作区
git reset <file>:重置暂存区的指定文件,与上一次提交保持一致,但工作区不变
git reset –hard [commit]:重置暂存区和工作区,与上一次或指定某次提交保持一致
	--keep:保持工作区和暂存区不变
git revert <commit>:新建一个提交,用来撤销指定的提交,后者的所有变化都将被前者抵消,并且应用到当前分支
git stash:保存并清除暂存区的更新
	pop:恢复暂存区更新

其他底层命令:

echo "<content>" | git hash-object --stdin:查看数据内容的SHA-1哈希值
	git hash-object <file>
	-w:存储数据,可通过find .git/objects -type f查看
git cat-file -p <SHA-1 value>:通过SHA-1哈希值获取内容
	-t: 返回类型

Git工作流

在Git网络中,每个开发者同时扮演着节点和集线器的角色,这就是说,每一个开发者都可以将自己的代码贡献到另外一个开发者的仓库中,或者建立自己的公共仓库,让其他开发者基于自己的工作开始,为自己的仓库贡献代码。于是,Git的分布式协作便可以衍生出种种不同的工作流程。

集中式工作流

集中式工作流程使用的都是单点协作模型。一个存放代码仓库的中心服务器,可以接受所有开发者提交的代码。所有的开发者都是普通的节点,作为中心集线器的消费者,平时的工作就是和中心仓库同步数据(见图5-1)。
集中式工作流
只需要配置好一台中心服务器,并给每个人推送数据的权限,就可以开展工作了。但如果提交代码时有冲突, Git 不会让用户覆盖他人代码,它直接驳回第二个人的提交操作,必须先拉取最新数据下来,解决冲突合并后,才能继续推送新的提交。绝大多数人都熟悉和了解这种模式的工作方式,所以使用也非常广泛。

集成管理员工作流

Git 允许使用多个远程仓库,开发者便可以建立自己的公共仓库,往里面写数据并共享给他人,而同时又可以从别人的仓库中提取他们的更新过来。这种情形通常都会有个代表着官方发布的项目仓库(blessed repository),开发者们由此仓库克隆出一个自己的公共仓库(developer public),然后将自己的提交推送上去,请求官方仓库的维护者拉取更新合并到主项目。维护者在自己的本地也有个克隆仓库(integration manager),他可以将你的公共仓库作为远程仓库添加进来,经过测试无误后合并到主干分支,然后再推送到官方仓库。工作流程看起来就像图5-2所示:

工作流程:

项目维护者可以推送数据到公共仓库blessed repository。  
贡献者克隆此仓库,修订或编写新代码。  
贡献者推送数据到自己的公共仓库developer public。  
贡献者给维护者发送邮件,请求拉取自己的最新修订。  
维护者在自己本地的integration manger仓库中,将贡献者的仓库加为远程仓库,合并更新并做测试。  
维护者将合并后的更新推送到主仓库blessed repository。  

集成管理员工作流
在GitHub网站上使用得最多的就是这种工作流,开发者可以克隆某个项目到自己的列表中,成为自己的公共仓库。随后将自己的更新提交到这个仓库,所有人都可以看到你的每次更新。这么做最主要的优点在于,你可以按照自己的节奏继续工作,而不必等待维护者处理你提交的更新;而维护者也可以按照自己的节奏,任何时候都可以过来处理你提交的更新。

司令官与副官工作流

这其实是上一种工作流的变体。一般超大型的项目才会用到这样的工作方式,如拥有数百协作开发者的Linux内核项目。各个集成管理员分别负责集成项目中的特定部分,所以称为副官(lieutenant)。而所有这些集成管理员头上还有一位负责统筹的总集成管理员,称为司令官(dictator)。司令官维护的仓库用于提供所有协作者拉取最新集成的项目代码。整个流程看起

工作流程:

一般的开发者在自己的特性分支上工作,并不定期地根据主干分支(dictator上的master)衍合。  
副官(lieutenant)将普通开发者的特性分支合并到自己的master分支中。  
司令官(dictator)将所有副官的master分支并入自己的master分支。  
司令官(dictator)将集成后的master分支推送到共享仓库blessedrepository中,以便所有其他开发者以此为基础进行衍合。  

司令官与副官工作流

团队项目的Git分支管理规范

参考https://www.cnblogs.com/spec-dog/p/11043371.html

分支管理

创建项目时(一般是服务型项目,工具型或辅助型项目可以简单一些),会针对不同环境创建三个常设分支:

develop:开发环境的稳定分支,公共开发环境基于该分支构建。
pre-release:测试环境的稳定分支,测试环境基于该分支构建。
master:生产环境的稳定分支,生产环境基于该分支构建。仅用来发布新版本,除了从pre-release或生产环境Bug修复分支进行merge,不接受任何其它修改

平时开发工作中,会根据需要由开发人员创建两类临时分支:

功能(feature)分支:为了开发某个特定功能,从develop分支上面分出来的。开发完成后,要merge到develop分支。功能分支的命名,可以采用feature-*的形式命名(*为任务号)
Bug修复(fixbug)分支:为了修复某个bug,从常设分支上面分出来的。修复完成后,再merge到对应的分支。Bug修复分支的命名,可以采用fixbug-*的形式命名(*为bug号)

流程规范

正常开发流程

流程:

从develop分支切出一个新分支,根据是功能还是bug,命名为feature-* 或fixbug-*。  
开发者完成开发,提交分支到远程仓库;  
开发者发起merge请求(可在gitlab页面“New merge request”),将新分支请求merge到develop分支,并提醒code reviewer进行review;  
code reviewer对代码review之后,若无问题,则接受merge请求,新分支merge到develop分支,同时可删除新建分支;若有问题,则不能进行merge,可close该请求,同时通知开发者在新分支上进行相应调整。调整完后提交代码重复review流程;  > 转测时,直接从当前develop分支merge到pre-release分支,重新构建测试环境完成转测;  
测试完成后,从pre-release分支merge到master分支,基于master分支构建生产环境完成上线。并对master分支打tag,tag名可为v1.0.0_2019032115(即版本号_上线时间);  

正常开发流程

并行开发测试环境Bug修复流程

并行开发(即前一个版本已经转测但未上线,后一个版本又已在开发中并部分合并到了develop分支)过程中,转测后测试环境发现的bug需要修复,但是develop分支此时又有新内容且该部分内容目前不计划转测,可以pre-release切出一个bug修复分支。完成之后需要同时merge到pre-release分支与develop分支。merge时参考“正常开发流程”。
并行开发测试环境Bug修复流程

生产环境Bug修复流程

生产环境的Bug分两种情况:

紧急Bug:严重影响用户使用的为紧急Bug,需立即进行修复。如关键业务流程存在问题,影响用户正常的业务行为。
非紧急Bug或优化:非关键业务流程问题,仅影响用户使用体验,或出现频率较小等,为非紧急Bug,可规划到后续版本进行修复。

非紧急Bug修复参考“正常开发流程”。
紧急Bug修复,需要从master分支切出一个bug修复分支,完成之后需要同时merge到master分支与develop分支(如果需要测试介入验证,则可先merge到pre-release分支,验证通过后再merge到master分支上线)。merge时参考“正常开发流程”。
生产环境Bug修复流程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值