Git 初体验

Mr.R0boter 于 2020-08-13 发布

前言

什么是 Git

Git 是一个版本管理系统,和其他版本控制系统最大的区别是,其他系统是基于差异的版本控制(即一组基础文件和每个文件随着时间变化积累的差异)。而 Git 是直接记录文件快照(相当于每次是将文件做了一次完整复制,每一次的记录都是一个全新的副本),在每一次存储文件之前会计算文件的校验和(Git 计算校验和使用的是 SHA-1 散列即哈希),Git 数据库中保存的信息都是以文件内容的哈希值来作为索引。

Git 中文件的三种状态

Tips:此外在工作区中新建但还未提交的文件会被标记为未跟踪状态(untracked)

Git 中的三个区域

Git 中的三个区域可以看作三棵不同的树,而 Git 则是用于专门管理这三棵树的工具

用途 区域
HEAD 上一次提交的快照,下一次提交的父节点 Git 仓库
Index 预期的下一次提交的快照 暂存区
Working Directory 沙盒 工作区

Tips:HEAD 是指当前分支引用的指针,它总是指向该分支上的最后一次提交,它属于 Git 仓库的一部分

其中 Git 仓库和暂存区包括一些当前仓库的 Git 设置都在项目根目录下的.git文件夹中,项目中其他位置则为工作区

Git 工作流程

一般情况下,Git 工作流程如下:

  1. 从 Git 仓库由 HEAD 指向的分支版本检出文件到工作区
  2. 工作区对文件进行增删改后将文件加入到暂存区
  3. 暂存区文件提交到 Git 仓库中永久保留,HEAD 移动到最新的分支版本处,如果是第一次初始化仓库则有略微差别。

首次初始化仓库时(即运行git init),只有工作区中存在文件,此时暂存区为空,仓库为空,HEAD 指向的是还未创建的默认的master分支。其工作流程如下:

  1. 使用git add *将所有文件添加到暂存区中
  2. 使用git commit将索引(暂存区)中的内容保存为永久快照(提交到 Git 仓库中),然后创建一个指向该快照的提交对象,最后更新master来指向本次提交。此时 HEAD 还是指向的master,但master不为空

Tips:当三棵树中的内容都一致时,使用git status没有输出,当其中任意一个与另外两个不同时使用git status则会获得提示

Git 中的配置

配置文件

配置方式

使用git config命令可以对 Git 进行配置

常用配置

Tips:当后面不跟设置的值时,默认是显示该选项的值,因此可以通过此命令查看已经设置的值

本地仓库

初始化

命令:git init

用处:将当前文件夹初始化为一个 git 仓库。所有的 git 命令都只在 git 仓库下才有意义,因此要使用 git 相关命令第一步是确保你在一个 git 仓库下

git 仓库下会有一个.git的文件夹,在 Linux 和 MacOS 下这是一个隐藏文件夹,要使用ls -a才能看到,这里面存放了关于仓库的所有信息,以及仓库中文件的所有信息,如果删除此文件夹,则 git 仓库就不再是一个仓库了

添加文件

命令:git add dir/filename

用处:当一个仓库初始化后,在该仓库下新增的文件还需要手动添加到该仓库中,才能实现对文件进行追踪和版本管理。使用git add表示将文件添加到暂存区,下次提交时会将暂存区中所有文件一并提交到本地仓库中

文件名应当是一个完整的路径,可以是相对路径也可以是绝对路径,但所有文件一定是在仓库根目录下面或仓库根目录下的各个子目录中,可以一次添加多个文件,也可以使用*表示所有文件,如果指定的是一个目录则会递归添加该目录下所有未跟踪或未暂存的文件

此命令不仅用于新建文件,文件被修改后也需要使用此命令将文件添加到暂存区,也能用于合并时将有冲突的文件标记为已解决状态

提交文件

命令:git commit -m "xxx"

用处:将添加的文件提交到仓库中,-m后指定的是此次提交的说明文字,一般用于简短描述此次编辑的作用,方便以后查找改动记录。如果有大段文字说明可以不使用-m,会默认启动你设置的文本编辑器来让你输入提交说明。提交时是提交的存放在暂存区的快照,如果在工作区修改了文件但并未加入到暂存区中则不会提交,提交是将当前暂存区的快照进行永久保存,以后可以随时回退到此状态或是进行比较

使用-a选项会将当前工作区中已跟踪的所有做过修改的文件直接提交,此参数实际上相当于先将工作区已修改文件全部添加到暂存区再进行提交,即跳过git add步骤

当提交时提交信息写错了或有几个文件忘记添加到暂存区导致没有提交,如果再按照正常流程就会在历史记录中多一次重复的提交记录,此时使用--amend选项可以覆盖前一次提交记录,此选项会强制提交当前暂存区的快照到仓库中,无论暂存区的文件是否有发生变化,没有变化则只会覆盖提交信息,有变化则完全覆盖上一次提交。这样可以尽可能的保持仓库历史

查看文件状态

命令:git status

用处:查看当前仓库中的文件都处于什么状态,一般为以下一种或多种类型,-v选项会输出更详细的提交说明

添加-s--short选项表示简略显示:

忽略文件

工作目录下有时会产生一些无需纳入版本管理的文件,如编译的临时文件,编辑的缓存文件,程序运行时产生的日志或其他临时文件,因此可以通过创建名为.gitignore的文件来指定仓库中忽略哪些文件不进行版本管理。一般来说只需要在仓库根目录下创建一个.gitignore即可,整个仓库都会递归应用该文件中指定的忽略的规则,也可以在子目录下单独创建,其作用返回只在该子目录下所有文件和文件夹

.gitignore文件中的格式规范如下:

  1. 所有空行和以#开头的行都会被忽略
  2. 可以使用标准 glob 模式匹配(即简化版正则),会递归应用到整个工作区
    1. *表示零个或多个任意字符
    2. []表示匹配中括号中任意一个字符或范围(以短横线连接的表示范围)
    3. ?表示单个任意字符
    4. **表示匹配任意中间目录
  3. 匹配模式可以以/开头防止递归
  4. 匹配模式可以以/结尾指定目录
  5. !开头表示取反,会忽略指定模式以外的文件或目录
  6. 每个规则一行
  7. 下面的规则优先级高于上面的规则

Tips:Github 上有一个十分详细的针对数十种项目及语言的.gitignore文件列表

查看修改细节

命令:git diff

作用:默认不带任何参数是用于比较当前工作区和暂存区中文件的具体变化内容,即当前工作区修改后但还没有添加到暂存区的文件修改了哪些内容,会以补丁形式显示出具体的修改内容。当添加--staged--cached(两个为同义词)参数时则表示比较暂存区和最后一次提交的文件的具体变化内容,即当前已添加到暂存区但还没有提交到本地仓库的文件具体修改了哪些内容,也是以补丁文件的形式显示具体修改内容

Tips:diff 可以调用外部图形化工具来比较差异如 vimdiff 等,使用git difftool --tool-help来查看当前系统支持哪些 Git Diff 插件

移除文件

命令:git rm

作用:在 Git 仓库中要删除某个文件,需要从暂存区和工作区都删除该文件,如果仅从磁盘上删除则文件还保留在暂存区中还需要手动提交一遍(否则会出现在未跟踪文件清单中),使用此命令则直接从工作区删除文件后并从暂存区移除并提交,不会出现在未暂存清单中

使用-f参数除了删除当前工作区中的文件,还会强制删除已添加到暂存区的文件

使用--cached参数可以仅删除已添加到暂存区的文件,仍保留当前工作区的文件(比如将编译生成文件不小心添加到暂存区就可以使用此命令删除)

此命令还支持.gitignore文件中的 glob 模式

移动文件

命令:git mv

作用:用于移动文件或重命名文件,相当于运行了三条命令mvgit rmgit add

查看历史

命令:git log

作用:默认情况下会显示所有提交最近的更新在最上面,此命令会列出每个提交的 SHA-1 校验值、作者名和电子邮件、提交具体时间以及提交说明

使用-num可以指定显示最近的指定数目的提交

使用-p--patch会将每次提交时的差异(即修改内容)以补丁格式输出

使用--stat会输出简略的统计信息,如几个文件产生了修改,新增了多少,删除了多少

使用--pretty=format可以自定义显示格式,其内建的有四种格式

选项 说明
%H 提交的完整的哈希值
%h 提交的简写的哈希值
%T 树的完整哈希值
%t 树的简写哈希值
%P 父提交的完整哈希值
%p 父提交的简写哈希值
%an 作者名字
%ae 作者的电子邮件地址
%ad 作者的修订日期(可以使用--date=选项来定制格式)
%ar 作者修订日期(按照多久以前来显示)
%cn 提交者的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期(按照多久以前来显示)
%s 提交说明

使用--graph可以在日志旁以 ASCII 图形显示分支和合并历史

使用--abbrev-commit会仅显示 SHA-1 校验值的前几个字符

使用--since=2.weeks--after列出最近两周的所有提交,也可以使用类似 2020-01-01 这种具体某一天的,或是 1 years 1 day 1 minutes ago 这种

使用--until--before--since一样的用法

使用--author列出指定作者的提交记录

使用--grep在提交说明中进行搜索

可以指定多个作者和说明搜索,这样会输出任意匹配到的提交,使用--all-match则只输出所有匹配到--grep模式的提交

使用-S指定一个字符串,只显示添加或删除了该字符串的提交

使用--no-merges在结果中排除掉合并提交的记录

重置文件

命令:git reset

作用:对 Git 中三棵树中的文件进行操作,将一个或多个区域的文件重置到指定的分支版本

检出文件

命令:git checkout