一、四大工作区域
Git本地有四个工作区域:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)、git仓库(Remote Directory)。文件在这四个区域之间的转换关系如下:
Workspace:工作区,就是你平时存放项目代码的地方
Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交的文件列表信息
Repository:仓库区(或版本库),就是安全存放数据的位置,这里面有你提交的所有版本的数据。其中HEAD指向最新放入仓库的版本
Remote:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑,用于远程数据交换
虽然我们知道逻辑上的工作区、暂存区和版本库,但是实际上他们又分别在哪里呢?如果我们无法和现实中的相关实物对照起来,可能大家学起来还是云里雾里,接下来让我一起来了解一下Git仓库以及各工作区域之间的具体情况。
二、Git仓库
如果我们使用Git Bash进入一个目录(比如:E:/test/),在这个目录下执行git init命令,就会在这个目录建立一个Repository(仓库),这个仓库就是我们被Git管理的仓库了,每个仓库(缩写repo)可以简单理解成一个目录,这个目录里面的所有文件都通过Git来实现版本管理,Git都能跟踪并记录在该目录中发生的所有更新。
那么为什么Git能跟踪并记录在仓库目录中的所有更新呢?因为仓库的这个目录中有一个“.git”的文件夹。这个文件夹非常重要,所有的版本信息,更新记录,以及Git进行仓库管理的相关信息全部保存在这个文件夹里面。所以,不要修改/删除其中的文件,以免造成数据的丢失。
为进一步了解Git仓库,请参考下面这张图,大概展示出了我们需要了解的基本知识。
Directory:使用Git管理的一个目录,也就是一个仓库,包含我们的工作空间和Git的管理空间。 WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间,除了.git之外的都属于工作区。 .git:存放Git管理信息的目录,初始化仓库的时候自动创建。 Index/Stage:暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区。 Local Repo:本地仓库,一个存放在本地的版本库;HEAD是一个指针,指向当前的开发分支(branch)。 Stash:是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态。
有了上面概念的了解,下面简单介绍仓库的文件结构。
hooks 目录
作用:包含客户端与服务端的钩子脚本。
Git 本身也是一个可拔插的程序【可自定义扩展】,它为用户交互仓库过程时提供了一些相对应的钩子函数来执行,同时开发人员也可以来自主编写这些钩子函数。
.sample 脚本文件
info 目录
作用:包含一个全局性排除文件。可自定义某些不需要 Git 管理的文件。
exclude 排除文件
logs目录
作用:保存日志信息。【其中包含 refs
被引用的分支及 HEAD 分支指针信息】。
refs:引用的分支 log 信息,打开refs文件夹,可以看到heads文件夹、remotes文件夹和stash文件;
stash文件存储的是所有你使用git stash命令暂存的记录,是一个列表。使用git stash list时,查询出的列表就是从stash中取出来的。
heads文件里面存储的是一系列的本地分支的对象(即文件),每个对象的文件名就是本地的一个分支名,使用git branch查看本地分支命令时,查询出的所有本地分支就是取的heads文件夹下所有文件的名称。
remotes文件夹里存储的是远端的一系列分支的对象,每个对象的文件名称就是远端的一个分支名称,使用git branch -a查看远端分支命令时,查询出的所有远程分支就是取的remotes文件夹下所有文件的名称。
HEAD 分支指针,主要记录每次的变更操作,所有类型的变更都会记录;git reflog命令查询出的列表就是HEAD中存储的列表。
objects目录
作用:存放所有的 git 对象,哈希值一共40位,前 2 位作为文件夹名称,后 38 位作为对象文件名。
refs 目录
作用:存放指向数据的提交对象的指针(分支)。
heads
: 该文件夹存储的是所有的本地分支文件,每一个本地分支文件中,存储的是一个哈希值,每一次commit都是生成一个对应的哈希值,然后用这次新生成的哈希值,替换掉原来这个分支文件中的哈希值。每当
git checkout -b
创建一个分支时,都会在refs/heads
目录下创建一个对应的分支文件,每个文件代表一个分支的提交,而分支文件内部保存的是最后一次提交对象的 hash
stash文件:该文件是使用git stash命令时,会将生成的git对象的哈希值存储到stash文件里,更进一步说stash文件中,就存了一个40位的哈希值。对应的git对象在objects文件夹里。使用git stash pop时,会先去stash文件中,找到该哈希值(或者也可以认为是指针),然后到对应的objects文件夹下,查找对应的git对象,将其中的数据取出来,转换成我们能看懂的代码。
tags文件夹:当使用git tag v1.0给当前分支,打上标签时,就会在tags文件夹下,生成对应文件,文件里存储的是当前分支所对应的哈希值,以后就可以使用v1.0这个标签来代替分支名称,通常发布稳定的线上版本时,使用这种做法。方便以后查询,因为使用标签容易记,更简洁。
config 配置文件
[core] :核心配置
[remote “origin”] :远程仓库来源地址
[branch “develop”]:分支信息
[user] : 本项目所用用户名和邮箱
index:暂存区(stage)
作用:暂存数据信息,是一个二进制文件。
HEAD 分支指针
作用:一个指针,指向了当前分支。
FETCH_HEAD
作用:一个临时的 refs
引用指向,用于跟踪刚刚从远程仓库中 fetch > pull
获取的内容。
ORIG_HEAD(可选)
作用:当使用 reset、merge、rebase 等风险操作时,Git 会将 HEAD 原来所指向 commit 对象的 sha-1 值存放于 ORIG_HEAD文件中。它可以让我们找到最近一次风险操作的 HEAD 位置。
packed-refs(可选)
作用:打包的tags标签及标头信息,用于高效的数据库访问。
COMMIT_EDITMSG
作用:存储上一次commit提交时-m的备注信息。
注意:图1中.git目录下有可能还有其他文件,但这是一个全新的 git init 生成的库,所以默认情况下这些就是你能看到的结构。
三、远程库和分支以及命令解析
1、远程库和分支解析
master :Git 的默认分支名字。它并不是一个特殊分支、跟其它分支完全没有区别。之所以几乎每一个仓库都有 master 分支,是因为git init命令默认创建它,并且大多数人都懒得去改动它。
origin:Git 克隆的仓库服务器的默认名字。
origin/master:是当本地的 master 分支同步到服务时的名字。如果分支名称为MyOwn、当分支同步到服务器时,会看到服务器上的名字为 origin/MyOwn。
origin/HEAD -> origin/master:origin/HEAD就像一个指针,表示默认分支,如下例子中它指向origin/main,即origin/main是默认分支。
[root@localhost]# git branch -r
origin/HEAD -> origin/main
origin/main
origin/wip-DRV-541
origin/wip-DRV-542
origin/wip-DRV-588
origin/wip-DRV-594
origin/wip-DRV-595
2、命令解析
1) git push origin HEAD:refs/for/master
总体格式:git push <远程主机名> <本地分支的名字> : <远程分支名>
git push :表示推送代码到远程服务器。
origin : 表示远程的库或远程主机的名字。
master:表示远程分支的名字。HEAD: 表示一个特别的指针,是指向你正在工作的本地分支的指针,可以当做是本地分支的别名。git通过它可以知道当前工作区间在哪个分支。
refs/for :表示我们提交代码到服务器之后是需要经过code review 之后才能进行merge操作的,而refs/heads是不需要的。
2) git pull origin master
总体格式:git pull <远程主机名> <远程分支名>:<本地分支名>
git pull:表示拉取代码到本地工作区
origin:表示远程的库或远程主机的名字
master: 此master为远程分支
注:此命令中省略了本地分支名