• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

git分支说明理解原理

武飞扬头像
Luke
帮助99

git是如何保存数据的

那么,git是如何来帮我们保存信息的? 首先我们需要知道,git在每次进行存储操作时,保存的不是文件的变化或者差异,而是存储的那一时刻的文件快照(可以理解为文件副本,二进制格式存储)。 在我们的本地仓库中,有个.git的隐藏文件夹,这个是git仓库的重要部分,当我们git init或者git clone时就会存在,里面objects目录存储所有快照(文件内容)(.git内容如果想了解,可以留言下次解读)。

当你提交一次更新(文件有修改),它就会对当时的全部文件创建一个快照如【图1-1】

【图1-1】

version1、version2、version3分别表示第一次、第二次、第三次提交

学新通技术网

除此之外,git会保存一个提交对象(commit object),这个提交对象包含了

  • 一个指向暂存内容快照的指针
  • 作者的姓名和邮箱
  • 提交时输入的信息
  • 指向父对象的指针
    • 首次提交操作产生的提交对象中没有父对象(参照【图1-2】提交对象里parent为空)

【图1-2】 学新通技术网

我们大部分的git操作基本都是基于本地来的,这让我们在开发的时候即使在没网没vpn的时候也可以很好的进行常规操作,等网恢复了再推送上去即可。 接下来,回到正题,说说分支

关于分支

分支是什么?

git的分支,本质上仅仅是指向提交对象的可变指针(如果有疑问,可以继续往下看)

分支包含本地分支和远程分支,先说本地分支

本地分支

git初始化时默认分支为master

当我们进行多次分支提交时,指针会随着提交向前移动。箭头指向上一次提交(父对象)如【图1-3】

【1-3】 学新通技术网

分支创建
git branch dev

创建分支,其实就是创建一个可以移动的新指针,如【图1-4】执行上述语句

【图1-4】 学新通技术网

分支切换
git checkout dev

切换分支后,HEAD游标指向到dev,效果如下

【图1-5】 学新通技术网

当前分支修改后提交,执行一下语句

git commit -am 'do some thing'

效果如下【图1-6】 学新通技术网

git 魔法快速创建并切换到branchName分支:

git checkout -b branchName
分支合并
git merge branchName

我们在dev进行了一些提交操作后,现在需要把dev的分支内容合并到master

git checkout master
git merge dev

merge合并操作,会将两只分支的最新快照(74jck和87dd3)合并,并与二者的最近的共同祖先(34ac2)进行三方合并,生成一个新的提交(9913f),且当前分支指针指向这个提交,如【图1-7】

【图1-7】 学新通技术网

分支删除

不难理解,分支删除就是删除对应的指针

  • git branch -d branchName

  • git branch -D branchName

    -d 删除本地分支,如果目标分支有提交还没合并,会删除失败 -D 强制删除本地分支i,不管目标分支是否有提交未合并

以上关于分支的描述是本地分支的操作,下面来看下远程分支

远程分支

与本地分支类似,远程分支也存在远程引用,也就是对远程仓库的引用。

举个例子 假设你的网络里有个git.xxx.com的git服务器,你从上面克隆 git的clone命令会自动为你将其命名为origin,拉取他的所有数据, 并创建一个指向它的master分支的指针,并且在本地将其命名为origin/master, git也会在本地创建一个与之对应的master分支,这样你就有工作的基础了。

克隆远程分支
git clone xxxx.git

如图【2-1】remote branch是远程分支引用 学新通技术网

需要注意的是,远程分支状态的引用,是你无法移动的本地引用,也就是你无法手动在本地切换远程分支的指向状态。

只有当你与远程origin服务器连接拉取最新数据,origin/master的指针才会自动移动。远程仓库与本地仓库指向不一致会导致提交不成功,所以一般我们在提交之前都会先同步一下远程分支代码。

举个例子,本地master分支提交版本到了C22,在未拉取远程分支的之前,本地origin/master分支还是指向还是上次的C2提交位置【图2-2】,拉取远程分支后,本地仓库origin/master分支指针就会同步指向远程分支的最新提交记录位置(C32)

【图2-2】 学新通技术网

更新远程跟踪分支
//remote 默认是origin 
git fetch <remote> 

可参考上述【图2-2】更新远程分支后,本地工作区代码并不会自动更新,还需要执行git merge命令合并到本地工作区 以本地master分支拉取远程master为例(注意哦origin/master是远程分支)

git merge origin/master

而我们常用的git pull 魔法就是结合了git fetch 和git merge

推送远程分支
git push <remote> <branch>

使用案例:

git push origin dev

这句命令,意味着,“推送本地的dev分支来更新远程的dev分支” 推送远程分支后,远程分支的提交记录指针往前移,跟本地提交类似,这里就偷个懒不画图了hhhh

你也可以另外命名:

//推送本地分支到远程dev2分支
git push origin dev:dev2

通过这种方式,可以推送本地分支到一个命名不相同的远程分支

跟踪分支

从一个远程跟踪分支检出一个本地分支会自动创建所谓的“跟踪分支”(与远程分支有直接关系的本地分支) 当克隆一个仓库时,通常会自动创建一个跟踪origin/master的master分支。 当然,如果你愿意的话,也可以设置其他的跟踪分支,或时一个其他远程仓库上的跟踪分支 比如执行:

git checkout -b <branch> <remote>/<branch>

如果想要本地分支与远程分支设置为不同的名字,可以使用如下命令(以检出远程dev分支为例)

git checkout -b test origin/dev

如下图【2-3】 学新通技术网 如果你尝试检出的分支不存在,且远程分支刚好有个名字与之匹配的分支,那么git会为你创建一个跟踪分支

git checkout newBranch

此命令会在本地创建一个远程分支newBranch的跟踪分支

删除远程分支

可以运行带有--delete的git push 命令来删除一个远程分支

git push origin --delete <branch>

分支变基(与merge不同的整合分支方式)

前面介绍过,merge命令整合分支,是将两个分支的最新快照以及二者最近的共同祖先进行三方合并,生成一个新的快照(并提交),分支之间会交叉存在 rebase 是将其中的一个分支的补丁和修改应用到另一个分支上,原来分支上的提交记录会被丢弃掉,还是图示举例说明 先看一个merge合并的方式:如下图

git checkout master
git merge dev

【图3-1】 学新通技术网

再看rebase的处理方式:

git checkout dev
git rebase master

合并效果如下: 【图3-2】 学新通技术网

此时,dev分支上的原c3提交已经丢弃掉,而master分支上多了一个与c3内容一致的c3',dev分支最新提交内容变成了c3',简单来说,就是以master分支的最新提交为基础,将原来dev的分支改动依次追加到master后面

它的原理是,找到dev和master的共同祖先C1,然后对比当前分支(dev)相对于该祖先C1的历次提交,提取相应的修改存为临时文件,然后将当前分支指向目标基底C2,最后将之前的临时修改文件依序应用。 接下来再进行一次合并,dev跟master分支指向的快照内容就一样了

关于分支变基的使用,网上褒贬不一,个人觉得,变基让你的提交记录更流畅,但是因为改变分支基础,提交记录也改变了,在多人合作的时候,很容易造成混乱,个人solo倒还好,简单举例说明:

ABC共同开发dev分支(最新提交c0),BC都拉取dev分支在本地,C提交了一次修改C1推到远程分支,B提交了C2修改并合并C1产生了新的提交记录C3推送到远程分支,如 【图3-3】 学新通技术网

这时候A拉取了远程分支,并做了提交C4,接下来B忽然本地回退了一下版本,并炫了一波rebase 然后提交了代码,推到远端,A又拉了一下代码,远程dev分支和A本地的分支结果会如下【图3-4】所示,C3部分的代码重复提交了两次,也就是原本B想丢弃的C2,C3提交,他又回来了,搞的很混乱

【图3-4】 学新通技术网

我个人保险起见,多人合作的分支不要用rebase,安安全全的 用merge

cherry-pick

merge和rebase常用来合并分支,但有时候我们只需要合并某一次的提交修改到分支上,这个时候,cherry-pick可以说是你的不二之选

比如我们有AB两个分支,分别有各自的提交记录,A分支最近提交为C5,B分支最近为C6,现在在B分支上cherryA分支的C3记录,执行

git checkout B
git cherry-pick C3(C3为当初提交的hash值)

效果如下【图4】所示 学新通技术网

如果想进行多个提交记录的合并,可以执行

git cherry-pick C3 C4 ...

或者后面的参数为分支名,则表示合并该分支最新的一次提交内容

git cherry-pick branchName

总结

我们常使用的分支操作大多是创建、合并,git对分支的管理当然远远不止这些,上面述说的也只是我们常用的一部分原理,实际使用过程可能会有很多其他的好用的git魔法。欢迎讨论,以上描述如有错漏,也期待指正。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanffabi
系列文章
更多 icon
同类精品
更多 icon
继续加载