项目人员使用git,几乎70%的工作都是在本地仓库完成的。由此可见本地仓库的重要性。

下面我们就通过一些基本的命令讲下git的本地仓库的结构,存储流程,数据类型,如何存储......

仓库结构

大家都晓得提交文件需要先git add 再Git commit。为了晓得add到哪里了,commit到哪里了。需要知道git仓库结构:工作区+暂存区+版本库。

工作区:就是你在电脑里能看到的项目目录。你所有本地的改动都是在工作区改动的。工作区是对项目的某个版本独立提取出来的内容。 是从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。

暂存区:暂存区是一个文件,一般在 Git 仓库目录中的index文件(.git/index)中,保存了下次将要提交的文件列表信息。 git ls-files --stage可查看暂存区内容。保存了所有文件对应的索引,即SHA1值。所以 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。

版本库:.git目录是 Git 用来保存项目的元数据,版本,分支的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。其中 .git/objects目录,被称为对象数据库。具体的目录详情看下图。

项目文件的状态

项目文件有四种状态,git可以管理的有三种状态: 已提交(committed)已修改(modified) 和 已暂存(staged)

第4个状态:未跟踪

  • 已修改:表示修改了文件(该文件曾经添加过版本库),但还没保存到数据库中。

  • 已暂存:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

  • 已提交:表示数据已经安全地保存在本地数据库中(所以也可称为未修改状态)。

  • 未跟踪:新创建的文件如果没有添加到暂存区,那git没办法对其跟踪,故而是‘未跟踪’状态。

项目文件状态与迁移:

当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。

当执行提交操作git commit时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。

当执行 git reset HEAD命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。

当执行git checkout . 或者 git checkout -- <file> 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。

当执行 git checkout HEAD ." 或者 "git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

项目文件迁移过程拆解

概念了解后,我们实际操作看下git文件管理流程~

一 创建一个git仓库

  1. 创建一个目录,进入目录
  2. 过git init 命令把这个目录变成Git可以管理的仓库

    (在/deploy/script/.git/下初始化了一个空的git版本库)
  3. ls -a 可发现多了一个.git目录。这个目录就是Git用来跟踪管理版本库的,所谓的git版本库
    平平无奇的目录/deploy/script/ 摇身一变成了一个git仓库了~~~

或者Git clone一个已有的远程仓库。拷贝的是.git目录。然后解压默认指定的master版本数据到工作区。

二 git add 过程拆解

提交文件到暂存区。这一步其实主要包含两个步骤:

1. git hash --object <file>

工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中

  1. 生成SHA-1值,并在版本库的objects目录下生成目录跟文件。用SHA-1[0:2]命名目录,SHA[2:40]命名文件名。

  2. 存储文件压缩后的数据。可通过git cat-file -p SHA-1查看object文件内容

2. git update-index <file>

更新index文件中提交文件的SHA-1值,也就是文件指向的objects地址。git ls-files --stage 可查看暂存区(index文件)的内容

三 git commit 过程拆解

git commit提交过程也可分为两个步骤:

  1. 计算每一个子目录(项目根目录)的校验和,然后在Git 仓库中将这些目录保存为树(tree)对象。子目录中包含的是blob对象。
  2. 相关提交信息+指向顶层树对象(项目根目录)的指针 合并生成一个commit 对象。如此它就可以在将来需要的时候,重现此次快照的内容了。
  3. 当前 分支会做相应的更新(.git/refs/heads 下文会详细说明)

git cat-file -p SHA-1 可查看objects文件下存储的内容,包括commit对象,和tree对象。

git cat-file -t SHA-1 可查看文件类型

例如:一个项目里假如有三个文件ReadME,LICENSE,test.rb,commit后仓库里会保存五个对象。(如果项目不只三个文件,还有子目录的话,那每个目录都会生成一个tree对象。)

对象模型

块-blob

也叫数据对象,文件的每一个版本表示为一个块(blob)。一个blob保存一个文件的数据,但不包含任何关于这个文件的元数据,甚至连文件名也没有。

目录树-tree

树对象,一个目录树对象代表一层目录信息,它记录blob标识符、路径名和在一个目录里所有文件的一些元数据。

提交-commit

提交对象,一个提交对象保存版本库中一次变化的元数据

格式很简单:它先指定一个顶层树对象,代表当前项目快照; 然后是可能存在的父提交(前面描述的提交对象并不存在任何父提交); 之后是作者/提交者信息(依据你的 user.name 和 user.email 配置来设定,外加一个时间戳); 留空一行,最后是提交注释。

标签-tag

标签对象,一个标签对象分配一个任意的且人类可读的名字给一个特定对象,通常是一个提交对象。

(本次不做分享。)

对象存储

你向 Git 仓库提交的所有对象都会有个头部信息一并被保存 git hash --object <file>
Git 首先会以识别出的对象的类型作为开头来构造一个头部信息。 接着 Git 会在头部的第一部分添加一个空格,随后是数据内容的字节数,最后是一个空字节(null byte):
比如数据对象 content = "hello world" 类型是‘blob’
头部存储方式:类型+空格+字节数+空字节
头部信息是:"blob 11\u0000"
Git 会将上述头部信息和原始数据拼接起来
存储的对象是:"blob 11\u0000hello world",并计算出这条新内容的 SHA-1 校验和

压缩新的数据对像:

SHA-1用来做存储对象的指针,指向的是.git/objects下的存储对象。
目录跟文件名对应SHA-1前2个字符和后38个字符。
存储的文件内容是压缩后的数据。

(commit,tree对象存储同理blob对象。)

本地分支

一 分支存储目录

.git/refs/heads/

在我们初始化一个git仓库的时候,会分配一个指针HEAD(.git/HEAD)表示当前分支的意思。且HEAD默认指向master分支 .git/refs/heads/master

如果切换分支为dev,HEAD就指向.git/refs/heads/dev了。由此可见,所有的分支都是存储在 .git/refs/heads/目录下的。同样也解释了,为何git切换分支如此迅速,因为知识更改了一个指针。

二 分支存储的内容

存储内容是分支最新一次的commit对象。

比如我们从master切换一个分支dev出来,可以看到master的commit对象跟dev的commit对象是完全一样的。

那如果修改下dev分支的文件内容提交,会发生什么呢?没错,dev分支的内容发生变更了,变成提交对象4b39a了。而master的内容没变还是之前的。可以git cat-files -p 4b39af8 查看版本快照

三 分支合并机制

我们切到master,合并dev分支。看到提示的内容,从f3c68...变成了4b39a....。也就是说简单的合并分支,只是把master的提交对象换成了dev的提交对象了。其他什么也没动。

这个‘快速合并’称为fast-forward合并策略。如果不希望直接合并可以:git merge --no-ff。

下面这种情况:master分支跟new分支都有改动,就不能快速合并。合并会会生成一个新的commit对象,父对象指向base跟new。

git原理-本地仓库认识的更多相关文章

  1. github仓库主页介绍、用git管理本地仓库和github仓库、搭建网站

    github仓库主页介绍 名词解释: 工作区: 添加.编辑.修改文件等动作 暂存区: 暂存已经修改的文件,最后统一提交到git中 git(仓库): 最终确定的文件保存到仓库,成为一个新的版本,并且对他 ...

  2. Git单人本地仓库操作

    本地仓库是个.git隐藏文件 以下为演示Git单人本地仓库操作 1.安装git sudo apt-get install git 密码:skylark 2.查看git安装结果 git 3.创建项目 在 ...

  3. 和同事合作开发,使用局域网 git创建本地仓库

    转自原文 和同事合作开发,使用局域网 git创建本地仓库 1.仓库 建一个空文件夹来做仓库,例如建为 cangku 1.1 cd 到 cangku目录下 创建远程仓库容器 mkdir  mycangk ...

  4. 使用Git初始化本地仓库并首次提交代码

    本文介绍使用Git初始化本地仓库,并首次提交代码到远程仓库GitLab上面. 首先,登录GitLab,创建一个新项目的私人仓库: 然后,在本地仓库(就是你写代码文件夹),右键,Git Bash Her ...

  5. 使用 Git 删除本地仓库和远端仓库文件

    使用 git bash 来删除 一.将文件(夹)添加到暂存区 这里假设本地和远端都有一个 test.txt 文件先在本地删除,通过 ·git status 查看通过git add test.txt 添 ...

  6. Git创建本地仓库&把pycharm项目添加GitHub仓库上

    一.创建本地仓库 1.1.下载Git地址:https://git-scm.com/downloads 下载完,一路next就可以 1.2.打开Git Bash输入: #创建一个learngit目录 $ ...

  7. 如何使用Git建立本地仓库并上传代码到GitHub

    使用Git建立本地仓库并上传代码到GitHub 工具/原料   电脑安装git客户端.注册github账号并登陆 方法/步骤     到本地项目文件夹右键选择git bash here   输入个人信 ...

  8. Git创建本地仓库

    使用Git创建本地仓库, 可以记录文本文件变化, 这里以自己的文章为例, 利用TortoiseGit工具创建一个本地Git仓库. 1. 切换到需要创建仓库的目录下, 比如:D:\MyDoc\Devel ...

  9. Git 创建本地仓库

    前面已经搭好环境了,现在我们缺的是一个管理版本控制的仓库.这次的实验是在电脑本地创建本地仓库.指定路径 默认的位置是在你所安装Git的目录下.Git的仓库你可以建在你电脑的任何目录下(最好不要包含有中 ...

随机推荐

  1. eclipse时一直卡在进程中

    (1)今天遇到进入eclipse时一直卡在 进程中,无论是重启电脑,还是重启软件 删除 D:\workspace\.metadata\.lock 文件才有用,特此记录下. (2)还有一种情况就是打开e ...

  2. Jenkins部署持续集成远程机节点的问题

    工作需要把工作电脑作为持续集成的执行机,最近研究Jenkins,在工作电脑上搭了一套环境,期间把原来的JDK删除掉了,导致持续集成的Jenkins节点slave-agent.jnlp打不开.解决方法是 ...

  3. GPRS DTU工作的原理与应用场景

    GPRS DTU是属于物联网无线数据终端设备的中一种,它主要是利用公用运营商的GPRS网络(又称G网)来为用户提供无线长距离数据传输的功能.一般都是采用的高性能工业级8/16/32位通信处理器和工业级 ...

  4. Hadoop高可用

    一.原因 - NameNode是HDFS的黑心配置HDFS有事hadoop的核心组件 NameNode 在Hadoop及群众至关重要 - NameNode的宕机导致集群的不可用 二.解决方案 其中 N ...

  5. Nodejs在VSCode下代码智能提示

    在学习Nodejs的过程中发现vscode下默认没有提示,在网上也测试了传统的一些方法,都不好用,最后找到这个npm install --save-dev @types/node

  6. Oracle初始——第一天

    一.数据库分类 1.小型数据库:access.foxbase 2.中型数据库:informix.sql server.mysql 3.大型数据库:sybase.db2.oracle 二.注释 1./* ...

  7. 线程池基本使用和ThreadPoolExecutor核心原理讲解

    原文地址:https://www.jianshu.com/p/ec5b8cccd87d java和spring都提供了线程池的框架 java提供的是Executors: spring提供的是Threa ...

  8. CF1320C World of Darkraft: Battle for Azathoth

    线段树 又是熟悉的感觉,又是E题写完了,没调完,不过还好上了紫 CF1295E 可以发现可以打败怪兽的关系类似二维偏序 那么首先考虑第一维(武器)以攻击值($a_{i}$)进行排序 把所有的怪兽以防御 ...

  9. Python基本数据类型与数据结构(数据挖掘学习)

    前言 最近工作和研究涉及到数据挖掘和机器学习,出于归纳和总结知识的目的写下这一系列的文章,这一系列文章将会包括Python的基本数据类型和数据结构,函数和面向对象相关的知识,然后会介绍数据挖掘和机器学 ...

  10. Java学习之路(一)——JDK的下载与安装

    (一).JDK是Java开发工具包 下载网址:https://www.oracle.com/java/technologies/javase-downloads.html (二).安装 下载JDK以后 ...