my-gitbook
Blog
  • 👨‍💻简介
  • 入门教程
    • markdown 入门教程
    • git 入门教程
      • 初识 git
        • 安装 git
        • 配置 git
      • 实战 git
        • 本地仓库
        • 版本管理
        • 回到过去
        • 基本概念
        • 版本控制
        • 撤销更改
        • 删除文件
        • 远程仓库
        • 分支管理
          • 分支总览
          • 冲突合并
          • 分支策略
          • 紧急修复
          • 变基合并
          • 协同开发
          • 本地和远程仓库的本质
        • 里程碑式标签
      • 私人定制
        • 忽略文件
        • 同步推送多Git仓库
      • 搭建私服
      • 扩展工具
        • git bash 常见命令
        • git bash 朋友圈
        • git bash 扩展tree命令
        • git bash 扩展命令(上)
        • git bash 扩展命令(中)
        • git bash 扩展命令(下)
        • git submodule 父子模块
      • 沙海拾贝
        • 知识速查
        • 备忘录[译]
    • github 入门教程
      • github 访问速度太慢
      • github 徽章从何而来
    • gitbook 入门教程
      • 准备阶段
        • 前置知识
        • 环境要求
      • 快速体验
        • gitbook-cli 命令行操作
        • gitbook-editor 编辑器操作
        • gitbook.com 官网操作
      • 高级进阶
        • 插件介绍
          • 实用插件
          • 主题插件
          • 开发插件
        • 导出电子书
        • 发布电子书
      • 公众号引流
      • 优化搜索
      • 常见问题
        • 热加载失败治标之法
        • 初始化默认折叠效果
      • 参考更多
  • 编程笔记
    • java 学习笔记
    • go 学习笔记
    • php 学习笔记
    • python 学习笔记
      • 入门教程
        • 00-ubuntu安装
        • 01-Linux基础
        • 操作系统的发展史(科普章节)
      • Django教程
        • Django 学习笔记
    • Linux 学习笔记
      • Linux基础
      • Linux全栈运维
  • 兴趣开发
    • 从零开始搭建服务器
      • 从登录服务器开始
      • 更加优雅地部署项目
      • 跟着官方体验 Docker
      • 快速尝鲜基于 Docker 部署项目
      • 利用阿里云 OSS部署静态网站
      • 免费实现https访问网站
      • webhook
    • 运维部署
      • docker 环境
      • docker 操作
      • docker compose
      • docker + nginx
      • docker + blog
      • docker + resume
      • docker + gitbook
      • docker + Bark
      • docker + py12306
      • docker + mojo-Weixin
      • docker + wechat-work-message-push-go
      • docker + email
      • docker + mysql
      • docker + springboot
      • docker + redis
      • docker + gogs
      • docker + gitlab
      • docker + gitea
      • docker + crawlab
    • 工具资源
      • 给 mac 装个 vmware 虚拟机
        • 给 mac 虚拟机装个 windows
        • 给 mac 虚拟机装个 centos
        • 给 mac 虚拟机装个 ubuntu
      • 给 windows 装个 vmware 虚拟机
        • 给 windows 虚拟机装个 mac
        • 给 windows 虚拟机装个 windows
        • 给 windows 虚拟机装个 centos
        • 给 windows 虚拟机装个 ubuntu
      • 公众号历史文章备份
        • Ryen
        • 苏生不惑
        • Python技术
      • 学会开发专属 chrome 插件
      • 攻克 12306 前端加密算法
    • 如何写作
      • markdown 和富文本
      • markdown 转富文本
      • csv 半手动数据统计
      • js 半手动数据统计
      • 简述优选文章统计
      • 快速上手Mermaid流程图
      • 常见问题
  • 读书观感
    • 大数据浪潮之巅:新技术商业制胜之道
  • 程序人生
    • 待完成清单
      • yarn快速入门
      • gulp快速入门
      • nvm快速入门
      • lodash快速入门
      • regexper快速入门
      • sublime快速入门
      • github 快速入门
      • svn 快速入门
      • java 快速入门
      • mysql 快速入门
      • maven 快速入门
      • tomcat 快速入门
      • gitignore 快速入门
      • android studio 快速入门
      • npm 快速入门
      • nginx 快速入门
    • 其他
      • 重装开发环境
      • 钉钉签到提醒
      • 倒计时提醒
      • 关注网站
      • 转型之路
      • 历史统计
      • 关于作者
      • 捐赠支持
由 GitBook 提供支持
在本页
  • 基本概念
  • 图解
  • 意图说明
  • 小结

这有帮助吗?

在GitHub上编辑
  1. 入门教程
  2. git 入门教程
  3. 实战 git

基本概念

上一页回到过去下一页版本控制

最后更新于1年前

这有帮助吗?

了解工作区,暂存区和版本库的区别和联系有助于我们更好理解 git 的工作流程,了解命令的操作意图.

git 和其他版本控制系统如 svn 的不同之处就是有暂存区的概念.

基本概念

  • 工作区 | Working Directory

正常情况下能看到的目录(不包括隐藏文件),也就是用户主动创建的目录

  • 暂存区 | Stage

工作区下的隐藏.git目录下的.index文件,因此也称为索引.

  • 版本库 | Repository

工作区下的隐藏目录.git目录

通过前几节我们知道,将文件纳入版本控制,需要分两步操作:

  • 第一步 git add 添加文件,实际上是将文件更改添加到暂存区.

  • 第二步 git commit 提交更改,实际上是将暂存区所有内容提交到当前分支.

我们使用 git init 命令初始化创建 git 仓库时,git 会自动创建唯一一个 master 分支,默认所有操作是在 master 分支上进行的,所以 git commit 就是徃 master 分支上提交更改的.

通俗地讲,文件更改可以多次添加到暂存区,即允许多次执行 git add 命令,然后一次性提交暂存区的全部更改到版本库,即只需要执行一次 git commit 命令即可.

说说个人理解 git 为何分成三部分进行版本控制操作,二部分行不行?

答案是肯定的,没有暂存区概念的 svn 同样可以进行版本控制,所以 git 增加暂存区必然是有存在的意外也就是所谓的好处的.

第一,暂存区的概念允许将本地文件的更改添加进来,也就是说本地文件的更改只有添加到暂存区才能进行下一步的提交更改,所以说那些更改添加到暂存区是由开发者本人决定的,这其实有了一定灵活性,并不是所有的更改都需要被记录!

第二,暂存区作为中间过程,暂存区的内容是打算提交更改的内容,也就是说暂存区可以视为一种临时缓存,用来记录预提交更改.实际工作中,新功能的开发并不是一蹴而就的,是由一系列的更改一起组成的,如果将这些更改分散开来单独提交,那势必会产生很多commit,如果等待全部工作完成再提交的话,解决了过多commit的问题,但是又遇到新问题就是你可能很长时间才能提交一次更改,失去了版本控制的意义.综上所述,暂存区的出现一种很好的解决方案,它允许将相关性代码添加在一起,方便后续提交更改时提交的都是相关性代码!

第三,作为分布式版本控制系统,不像集中式控制系统那样,对网络强相关,失去网络的 svn 是没办法再进行版本控制的,但失去网络的 git 仍然可以进行版本控制,只不过不能远程操作了而已,不过这部分也是无可厚非的,正所谓"巧妇难为无米之炊",你总不能要求断网下继续访问百度吧!

好了,我们继续回到 git 常用操作上,看一下工作区,暂存区和版本库三者如何协同工作的.

首先,先修改test.txt文件.

# 查看 test.txt 文件内容
$ cat test.txt
git test
git init
git diff
understand how git control version
# 追加 how git work 到 test.txt 文件
$ echo "how git work" >> test.txt
# 再次查看 test.txt 文件内容
$ cat test.txt
git test
git init
git diff
understand how git control version
how git work
$ 

紧接着新建newFile.txt 并随便输入内容:

# 查看当前文件夹下全部文件
$ ls .
file1.txt   file2.txt   file3.txt   test.txt
# 创建新文件 newFile.txt
$ touch newFile.txt
# 再次查看当前文件夹下全部文件
$ ls
file1.txt   file2.txt   file3.txt   newFile.txt test.txt
# 输入 add newFile.txt 文件内容 到 newFile.txt 文件
$ echo "add newFile.txt" > newFile.txt
# 查看 newFile.txt 文件内容
$ cat newFile.txt
add newFile.txt
$ 

现在运行git status 命令查看当前文件状态:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   test.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    .DS_Store
    newFile.txt

no changes added to commit (use "git add" and/or "git commit -a")
$ 

从输出结果中得知,test.txt 文件已修改(modified),还没添加到暂存区,而newFile.txt 文件还没被跟踪(Untracked).

现在我们使用git add 命令将 test.txt 和 newFile.txt 都添加到暂存区,再用 git status 查看文件状态:

# 添加 test.txt 文件
git add test.txt
# 添加 newFile.txt 文件
git add newFile.txt
# 查看文件状态
git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   newFile.txt
    modified:   test.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    .DS_Store
$ 

现在输出结果和上次就不一样了,显示的是即将被提交文件,其中 newFile.txt 是新文件(new file),test.txt 是修改文件(modified).

所以,git add 命令作用是将需要提交的更改文件临时放到暂存区中,然后执行git commit 命令就可以一次性将暂存区的所有内容提交到当前分支.

$ git commit -m "understand how stage works"
[master a5cd3fb] understand how stage works
 2 files changed, 2 insertions(+)
 create mode 100644 newFile.txt
$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    .DS_Store

nothing added to commit but untracked files present (use "git add" to track)
$ 

暂存区的所有内容提交到版本库,所以运行git status 时,工作区是干净的,即此时暂存区没有内容了!

.DS_Store 是 mac 电脑自动生成的文件,可以暂不理会,等到后面的.gitignore 文件时再处理.

图解

下图展示了工作区,暂存区,版本库之间的关系:

图中左侧是工作区,右侧是版本库,版本库中标记index 的区域是暂存区,标记 master 的是 master 分支所代表的目录树.

HEAD 是指向 master 分支的指针,标记 objects 的区域是 git 的对象库,真实路径位于.git/objects目录下,用于表示创建的对象和内容.

意图说明

  • git add 添加文件

工作区的修改或者新增的文件执行git add 命令后,暂存区(index)的目录树会自动更新,同时引发这次变化的文件内容会被记录下来,即生成对象库(objects)中的新对象,而对象的 id会被记录到暂存区的文件索引(index)中.

  • git commit 提交文件

暂存区的目录树写入到对象库(objects),master 分支的目录树自动更新.

  • git reset HEAD 撤销文件

暂存区的目录树被重写,被master 分支的目录树所替换,但是工作区不受影响.

  • git rm --cached <file> 删除缓存文件

删除暂存区文件,工作区不受影响.

  • git checkout . 检出文件

暂存区的文件替换工作区文件,注意:当前尚未添加到暂存区的改动会全部丢失!

  • git checkout HEAD . 检出文件

HEAD 指针指向的 master 分支中的文件替换暂存区以及工作区文件,注意:不仅清除工作区未提交的改动,连暂存区未提交的改动也会被清除!

小结

以上就是常用命令的背后意图,主要是工作区,暂存区和版本库之间文件同步策略的关系.

  • git add 是工作区更新到暂存区

  • git commit 是暂存区更新到版本库

  • git reset HEAD 是版本库更新到暂存区

  • git checkout -- <file> 是暂存区更新到工作区

  • git checkout HEAD <file> 是版本库同时更新暂存区和工作区

  • git rm --cached 清空暂存区

working-directory
repository
relationship