求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
 
   
分享到
Git命令家底儿及Git数据通信原理详解
 
作者 : 周立伟  来源:csdn  发布于 2016-6-24
 
Git是一款开源的分布式版本控制系统(VCS),常用的VCS工具还包括SVN、Mercurial等,他们的使命是对资源变化的进行版本管理控制,对资源容灾备份,支持多域协同开发。这里的资源不仅仅是系统代码,还包括图片、文件、网页等。本篇文章结合流程图、详细的注解、实例操作针对Git的使用、Git数据通信原理进行细致的讲解,利用半场足球赛的时间通读全文后相信你面对Git会自信满满、知其所以然,使用起来游刃有余,当然对其他工具的理解也就非常容易了。

Git在各个操作系统的安装过程就不缀文了,步骤都是固定的,按照步骤一步一步安装就可以了。在开始讲解之前,我们先对Git进行资源版本管理有个整体的了解,如图1为Git资源状态流转过程,理解清楚这个流转图对Git命令的操作非常关键。

接下来,我们开始梦幻的Git命令之旅,了解下在项目协同工作过程中经常使用的Git命令。以下是我在工作过程中的总结(可以说是我的Git家底儿了),为了更清晰的展示,将命令操作分成了有序的多块,大家在阅读过程中可能会感觉到一丝笔记的色彩,没错,这就是这篇文章的特点,我相信这种方式会更利于大家理解。

(PS:下文中【】的内容为对命令的注解)

git init                       
【初始化本地仓库 ,将当前项目目录加入git管理】
git add <filename||path> 【将新文件加入版本控制, Git会对目标文件进行跟踪, 纳入版本控制管理。 (这是个多功能命令, 根据目标文件的状态不同, 此命令的效果也不同:可以用它开始跟踪新文件, 或者把已跟踪的文件放到暂存区, 还能用于合并时把有冲突的文件标记为已解决状态等)】
git add . 【将当前目录所有文件加入到版本控制】
git commit -m 'commit comment' 【提交变动,将修改的文件转移到暂存区】
git commit -a 'commit comment' 【将add和commit操作合并】
git commit --amend 【重新commit,将之前commit合并为一个 (add上次commit漏掉的文件或者重写comment)】
Example: git commit -m 'commit comment'
git add filename
git commit –amend

此例子只会产生一次commit log,第二个commit会覆盖第一个commit。

取消已暂存到暂存域的文件或者修改未提交的文件,可以通过git status命令查看取消到命令方案。

<–clone start–>

如果我们想加入一个现有项目的协同开发,可以通过clone命令将远程reposity的项目克隆镜像到本地,此镜像(此处可以联想下操作系统的镜像)包含项目所有历史变更,所有历史版本,所有分支信息等等,是远程reposity的一个完整副本。Git支持多种数据传输协议,本地传输、git协议、ssh协议、http协议。

git clone source. zhouliwei.com/app/zhouliwei.git            
【本地仓库clone】 
git clone git+ssh://gitusername@192.168.0.1/zhouliwei.git 【远程仓库clone(ssh协议)】
git clone http://gitusername@source.zhouliwei.com/app/ zhouliwei.git 【远程仓库clone(http协议)】
git clone -l /home/zhouliwei/test 【拷贝本地资源库到当前目录】
git clone -b 分支名 http://gitusername@source. zhouliwei.com/app/test.git 【clone指定分支(类似checkout)】
git clone -s 远程地址 【作为共享仓库】

<–clone end–>

 git status           【查看当前版本状态。
该命令有几个信息块:
on branch branchname:本地资源库在branchname分支
changes not staged for commit:本地资源库做了哪些修改,还未commit到暂存域
new file:还没有加入版本控制的新文件
modified:有改动的文件
deleted:被执行删除的文件 git rm filename
unmerged:出现冲突的文件】


在协同开发的过程中,可能会对资源进行多次修改,多次提交,在一些场景下对提交历史的回顾极为重要,我们可以借助log命令完成此工作。

git log                【显示所有历史提交日志,最近的在第一行】 
git log -1 【显示最近一行】
git log --stat 【显示提交日志及相关变动文件,增改行统计】
git log -p -1 【详细显示每次提交的内容差异】
git log -p -m

git clean --df             【是从工作目录中移除没有track的文件】 
git rm –cached <filename||path> 【将文件或者路径从远程reposity、 、本地暂存域中删除,在本地工作空间中保留, 主要针对和项目本身无关的不小心提交到服务器的文件】
vim filename 【查看、编辑资源文件】

接下来我们了解下Git branch,分支可以说是一个非常具有魅力的创造,他将协作的成员工作独立起来,互不影响,各自沿着自己的主线向前推进,他们以master分支作为共同的资源集散地,所有分支生成于master,最终又回归到master。图2为Git 的分支模型。

<–branch start–>

每次commit都会在暂存域中生成一个快照对象,生成一个新的版本,分支就是指向快照对象的可变指针。可以通过HEAD定位到当前在哪个分支工作,HEAD是一个指向正在工作本地分支的特殊指针,可以通过checkout将HEAD切换成目标分支。HEAD会随着当前分支的commit而移动,其他分支不受影响。

  git branch          【列出本地所有分支(已检出)】 
git branch -a 【列出本地+远程所有分支】
git branch -v 【可以看见每一个分支的最后一次提交】
git branch -av
git branch -r 【列出所有原创分支(origin/.)】
git branch branchname 【创建一个新分支】
git branch -d 分支名 【删除一个分支】
git branch -m oldbranch newbranch 【本地分支改名】
git branch --contains 字符串 【显示包含目标字符串的分支】
git branch --merged 【显示所有已合并到当前分支的分支】
git branch --no-merged 【显示所有未合并到当前分支的分支】
git branch --set-upstream 分支名 origin/分支名 【本地分支关联到远程路径】

<–branch end–>

<–checkout start–>

从远程reposity checkout的下来的本地分支称为跟踪分支,跟踪分支是一个和某个远程分支映射的本地分支。clone之后本地会自动创建一个跟踪分支master,映射到远程的分支origin/master。

git checkout  branchname        【切换到新分支】 
git checkout -b branchname 【创建并切换到新的分支, 如果本地已经有此分支则使用上个命令】
git checkout -b branchna me origin/branchname 【在本地创建新分支,从远程拉取新分支代码】
git checkout filename 【替换本地改动,会从服务器下载最新的文件(HEAD 中最新的内容) 覆盖工作目录中的文件(add、commit的文件不受影响),次这个操作是不可逆】

<–checkout end–>

<–merge start–>

在协同项目工作的过程中,如果多个人同时修改一个文件的相同地方,leader在master上进行合并时难免会出现代码冲突的情况,此时的merge会合并失败,需要将冲突进行处理,我们可以采取下面方式进行处理。

git merge branchname || origin/branchname  
 【合并目标分支到当前分支,合并之后会生成一个新的快照对象】 

如果出现冲突,通过git status查看冲突位置(标记为unmerged为重读文件)。我们可以通过手动修改成想要的代码, 解决冲突的时候可以用到git diff ,处理完之后用git add

git reset --hard HEAD 【将当前版本重置为HEAD(通常用于merge失败回退)】
丢弃所有的本地改动与提交:

git fetch origin  【1.从服务器拉取最新版本】 
git reset --hard origin/master 【2.将你本地主分支指向到远程分支】

<–merge end–>

<–fetch start–>

git fetch  --all 

【 从远处资源库拉取所有分支(merge之后才会更新本地分支),可以进行diff、log
git fetch origin
【将从远程拉取上次克隆后的master分支所有变化,即获取master分支最新代码】

通过fetch命令合并代码过程:


git fetch     origin  branchname1  
【1. <远程主机名> <分支名>
设置当前的fetch_head为分支branchname
(fetch_head为每个分支在服务器上的最新状态)】
git fetch origin branchname1: branchname2
【2. 拉取远程branchname1到本地新分支branchname2(branchname2是一个临时分支) 】
git fetch diff branchname2
【3. 将当前分支和新建的临时分支branchname2进行比较】
git fetch merge branchname2
【 4. 将当前分支和新建的临时分支branchname2进行合并,
此时branchname1为最新代码】
git fetch -d branchname2
【5.删除临时分支branchname2】

git pull == git fetch + merge 【从远程拉取最新版本,合并】
git pull origin branchname1 【拉取并合并branchname1】

使用git fetch操作性更好些(和pull对比),我们可以进行diff、log,再merge,更利于开发者根据当前情况进行针对性操作。

<–fetch end–>

<–push start–>

通过push命令将自己的分支资源和协同小组的其他人员进行共享,前提条件是Git账户必须拥有远程reposity的写权限。

git pull  <远程主机名> <远程分支名>:<本地分支名> 
git push <远程主机名> <本地分支名>:<远程分支名>
【将本地分支推送到远程分支】
1) git push origin <本地分支名>
【远程分支名为空,将本地分支推送到远程与其有对映关系的分支】
2) git push origin :<远程分支名>
【本地分支名为空,将本地空分支推送到远程分支,即删除远程分支】
3) git push origin
【将本地当前分支推送到远程与其有对映关系的分支】

<–push end–>

<–remote start–>

参与项目的协作开发,本地资源来源于远程仓库,所以需要对远程仓库的管理,比如远程仓库的创建、查看、删除、client-server资源映射等等。

git remote      【列出远程所有alias别名,自己权限范围内的远程reposity】 
git remote -v 【可以看见每一个别名对应的实际url】
git remote add [alias] [url] 【给远程url添加别名||把url添加为远程仓库】
git remote add myRepo /home/zhouliwei/test.git
【添加本地仓库作为远程仓库,共享目录】
git remote rm [alias] 【删除一个别名】
git remote rename [old-alias] [new-alias] 【重命名】
git remote set-url [alias] [url]
【更新url. 可以加上—push和fetch参数,为同一个别名set不同的存取地址. 】
git remote add origin <server>
【将本地仓库连接到远程仓库
git remote add origin http://gitusername@source.zhouliwei.com/app/test.git
然后可以通过git push origin branchname将branchname推送到相应远程分支;创建远程仓库】
git remote show origin 【显示远程信息】

<–remote end–>

将本地工作空间上传到远程新建仓库操作:

首先在本地空间生成用于ssh加密传输的公钥和私钥,将公钥维护到远程仓库的SSH key(后面会详细介绍如何操作)。

git init
git add .
git commit –m ‘initial commit’
git remote add origin http://gitusername@source.zhouliwei.com/app/test.git
git push orgin masters

<–rebase start–>

可以通过rebase命令(衍合)以补丁的方式将某个分支的改动在其他分支上再打一遍(合并到其他分支),可以简化分支的历史操作记录,流程看起来更清晰(和merge对比)。

git checkout branchname 
git rebase master

将branchname分支代码的改动衍合到master,相当于是在master上复制了branchname分支的改动,只在master分支上生成操作历史。

<–rebase end–>

至此我们已经完成了常用Git命令的讲解,包括本地仓库的创建初始化、克隆远程资源,本地仓库资源的修改、提交、推送,分支的管理,远程仓库资源的检出,冲突处理,远程仓库管理、协同开发等等。每个命令模块讲解过程中的注解已经非常详细了,并且为了便于更好的理解列举了相应的示例,对于使用Git进行项目协同开发的人员来说,上面的内容可以说是绰绰有余了。

接下来,我们顺着Git的梦幻之旅继续往下走。项目协作的各个成员是如何与Git服务端进行数据通信的呢?之前我们有提到Git支持四种数据传输协议,那么我们来深入了解下这四种传输协议各自的优势和不足。

传输协议 优势 缺点
本地传输 1. 远程仓库部署在本地目录,Git client-server之间的数据通信类似本地文件的复制剪切,数据的通信速度较快;2. 资源的权限沿用本地操作系统的文件权限和网络访问权限,不需要单独配置。 1. 由于远程仓库在本地目录,资源毁灭性丢失的危险性增大。
ssh协议(安全外壳传输协议ssh://) 1. 服务搭建相对较简单;2. 基于公钥私钥对的方式进行加密授权数据传输;3. 同时支持数据的读和写操作。 1. 不支持匿名访问,必须通过ssh访问主机才能读写仓库。
Git协议(git://) 1. 自身携带的传输协议,传输速度最快的协议;2. 使用类似ssh相同的数据传输机制,但取消了加密解密的开销。 没有授权机制,要么所有客户端都可读,要么所有客户端都可写,不能根据情况选择性配置读写权限;2. 服务搭建相对较复杂。
http/https协议(超文本传输协议) 服务搭建相对较简单,基于Apache等web容器就可以实现;2. 授权机制简单,能够访问Git仓库所在服务器的web服务的人都可以获取远程仓库资源。 1. 数据通信网络开销较大;2. 执行写操作需要基于ssh协议。
通过上面的对比分析,我们发现http/https是最简单最流行的一种协议方式,ssh是最安全的一种协议方式,特别是在互联网领域这一点尤为重要,并且http/https的写操作也是基于ssh协议完成的,那么我们继续深入的了解下ssh通信协议。

ssh数据通信协议也称作安全外壳协议,从他的名字就可以看出他使命就是确保安全数据传输,并且传输的数据会进行压缩,降低网络传输消耗,提高数据传输速度。ssh协议是基于公钥私钥对的方式进行加密授权数据传输的,下面我们通过两个加密算法来理解公钥私钥——对称加密算法和非对称加密算法。

图3为对称加密算法流程图,数据的发送方sender和接收方receiver通过相同的密钥key对数据进行加密解密操作。秘钥用于确保数据在公共通道传输过程中的安全性,即使密文数据在传输过程中被外部窃取,如果没有密钥也不能获取其中的内容。

图4为非对称加密算法流程图,数据的发送方sender和接收方receiver通过不同的密钥key对数据进行加密解密操作。sender通过公钥key1对明文数据进行加密,receiver通过私钥key2对密文数据进行解密。公钥和私钥一定是成对出现的,如果一个文件用公钥进行加密,则可以通过私钥进行解密;如果一个文件用私钥进行加密,则可以通过公钥进行解密。比如,我们在互联网环境中和其他合作方进行数据通信,我们的私钥是保密的,只有自己知道,公钥可以分发给合作方1,合作方2等等,这些合作方可以通过公钥对数据进行加密传送给我们,然后我们通过自己的私钥进行解密,并且在这个过程中合作方之间是独立的数据安全的,不会看到其他其他合作方的数据,这也是非对称加密的一个优势。

接着,我们来看下如果生成属于自己的公钥和私钥。

在Git窗口输入ssh-keygen –t rsa –C “zhouliwei555@163.com”命令,回车,如图5。

图5 生成公钥私钥

在提示信息的目录中,我们看到生成两个文件,id_rsa.pub为公钥文件,id_rsa为私钥文件,如图6。

(在Mac中,切换到.ssh目录(cd .ssh),执行ssh-keygen –t rsa –C “zhouliwei555@163.com”,生成私钥和公钥)

图6 公钥私钥文件

生成的公钥和私钥怎么使用呢?现在我们使用SourceTree基于ssh协议从github上clone一个项目,会发现图7 ssh认证失败提示。

图7 ssh认证失败

为什么会ssh认证失败呢?提示信息描述的很清楚,我们需要将自己生成的公钥加入到github维护的该项目中(这个操作由该项目管理员完成,一个项目可能会被加入多个公钥),加入之后配合本地的私钥就可以进行安全的数据通信了,此时客户端就拥有了该项目的写权限,然后重新尝试clone,克隆项目成功。

回过头来,思考下Git基于http/https通信协议的写权限是不是也是通过这种方式实现的呢?答案是肯定的。

现在到了可以庆祝的时刻了,你不但可以熟练使用Git命令进行协同工作,还透彻的了解了Git数据通信的内部原理。知其然并知其所以然,将知识运用到实践中,才是研究技术的最高境界。

相关文章

每日构建解决方案
如何制定有效的配置管理流程
配置管理主要活动及实现方法
构建管理入门
相关文档

配置管理流程
配置管理白皮书
CM09_C配置管理标准
使用SVN进行版本控制
相关课程

配置管理实践
配置管理方法、工具与应用
多层次集成配置管理
产品发布管理
 
分享到
 
 
   


软件配置管理的问题、目的
软件配置管理规范
CQWeb 7.1性能测试与调优指南
为什么需要使用ClearCase
ClearCase与RTC的集成
利用ClearQuest 进行测试管理
更多...   


产品发布管理
配置管理方法、实践、工具
多层次集成配置管理
使用CC与CQ进行项目实践
CVS与配置管理
Subversion管理员


配置管理实践(从组织级到项目级)
通号院 配置管理规范与应用
配置管理日构建及持续集成
丹佛斯 ClearCase与配置管理
中国移动 软件配置管理
中国银行 软件配置管理
天津华翼蓝天科技 配置管理与Pvcs