Git: 基础原理

Git 的基本原理和使用。

原理

概念

工作区(工作目录):git 将一个目录作为工作目录,目录中文件的不断的变化,Git 不断的追踪这些文件的变化。

在这个过程中 git 将文件的状态大致可以分成了 5 种:

  • none (表示文件还不存在)
  • untracked(文件存在,但是没有被 git 管理)
  • modified (文件被修改,其前置状态是 staged 或者 commited)
  • staged (文件被 git 暂是记录下来)
  • committed(文件被保存到 git 仓库)

文件变动的过程中,git 会记录这些文件每个状态的样子。有点费解可以参考下面关于 staged 状态变为 modified 状态的情况。
一个文件经历过这些变化才会被 git 真正的记录下来,明白这些变化的过程,就可以明白 git 具体做了什么事情。事实上绝大部分的 git 命令都是在使文件在这些状态之间切换。

文件被提交的过程

图里列举了两个典型的案例:

  • 绿色部分代表一个新文件被提交的过程
  • 黄色部分代表一个文件被改动后之后再被提交的过程
sequenceDiagram
    participant none      as none
    participant untracked as untracked
    participant modified  as modified 
    participant staged    as staged
    participant committed as committed

    rect rgb(123, 237, 159)
    none      ->> untracked: 新创建文件
    untracked ->> staged: git add 
    staged    ->> committed: git commit
    end

    rect rgb(236, 204, 104)
    committed ->> modified: 修改文件
    modified  ->> staged: git add
    staged    ->> modified: 修改文件
    end

%%

先来看看一个新文件的状态是怎么变化的:

  • 文件默认不存在,可以认为这个文件的状态是 none,当文件被创建,git 就认为它是 untracked 状态。
  • git add 命令将 untracked 状态变为 staged 的状态,之后便可以被 git 追踪到 该文件的变化。
  • git commit 命令 staged 状态变为 committed 状态,这个动作会让 git 保存文件 staged 状态下的快照。每一次快照会有一个 commitID 作为唯一标识被固定下来。

再来看看一次对已有文件的改动有哪些状态变化:

  • committed 状态的文件被改动后 会被标记成 modified
  • modified 通过 git add 命令 会被标记成 staged 状态,之后可以被 git commit 命令记录下来。
  • 图中的虚线表示在 staged 状态修改文件之后,文件会被叫标记成 modified 状态,这时候,git 同时记录了这两种状态的文件版本;此时在 modified 状态执行 git commit 命令实际记录的是 staged 状态的文件内容。

撤销修改时的状态变化过程

git 好用的地方在于提供了足够多的回退方法。文件几乎可以在各个状态间回退而不丢失修改的内容,从而撤销内容或者提交。

自己整理的一些状态流转过程:

sequenceDiagram
    participant untracked as untracked
    participant modified  as modified 
    participant staged    as staged
    participant committed as committed

    rect rgb(255, 127, 80)
        committed ->> staged: git reset --soft 
        committed ->> modified: git reset
        committed ->> untracked: git rm --cached
        staged    ->> modified: git reset
        modified  ->> committed: git checkout(回到上次提交,丢弃改动)
    end
%%
  • 以上的过程除个别标注外,不会丢失代码的改动。其改动的仅是 git 记录的版本信息,代码的工作量不会丢失。
  • 慎用各种回退命令,不同的状态下使用可能会丢失对代码的修改。

一些资料

  • Pro Git: 权威的开源书籍,已经有中文译本了。稍微有点枯燥,作为手册来说很好用。
  • 图解 Git: github 一个开源库,详细讲了 git 的 commit 之间的变换原理。