LV01-Git-04-Git本地仓库-01-基础操作

本文主要是Git本地仓库中的一些基本操作的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
点击查看本文参考资料
点击查看相关文件下载
--- ---

【说明】本节笔记的相关操作在Windows下进行,因为VS Code有个Git的插件,可以很直观的演示一些东西。由于Git安装后自带一个Git-Bash终端,所以就不用Win下的命令行啦,就用的这个终端,因为它里边的命令与Linux很类似,而windows中的命令行有些命令与linux并不相同,为了统一,还是用用Git自带的终端啦。另外VS Code是可以选择使用的终端的,我直接将VS Code使用的终端改成了git-bash,这样更方便一些。

一、工作区域

1. 三大工作区域

image-20220110145428667

前边我们知道, Git 有三种状态,文件可能处于其中之一: 已提交(committed)已修改(modified)已暂存(staged),下边说的数据库起始就上上边图里边的版本库,感觉叫版本库好像更容易理解一些。

  • 已修改表示修改了文件,但还没保存到数据库中。
  • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交表示数据已经安全地保存在本地数据库中。

2. 记录每次更新到仓库

假设我们的机器上有了一个 真实项目 的 Git 仓库,并从这个仓库中检出了所有文件的 工作副本。 通常,我们会对这些文件做些修改,每当完成了一个阶段的目标,想要将记录下它时,就将它提交到仓库。

我们的工作目录下的每一个文件都不外乎这两种状态:已跟踪未跟踪。 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后, 它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 Git 已经知道的文件。

工作目录中除已跟踪文件外的其它所有文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 Git 刚刚检出了它们, 而你尚未编辑过它们。

编辑过某些文件之后,由于自上次提交后我们对它们做了修改,Git 将它们标记为已修改文件。 在工作时,我们可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。

Git 下文件生命周期图。

一个文件的状态变化周期如上图所示。

二、Git基础操作

1. 获取仓库

这里主要是在本地使用,所以我们可以在已存在目录中初始化仓库,我们可以准备一个目录,然后执行以下命令:

1
git init

然后我们会得到以下提示信息:

image-20230622083902793

我们查看一下这个目录有什么变化,发现多了一个.git目录,并且,在我们的目录名后边多了一个 master ,这个就是我们默认创建的分支,后边会详细学习。

image-20230622084006999

这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可,新初始化的 .git 目录结构如下。

image-20230622085457263

.git里边的文件就是记录每次提交以及每个文件状态的,还有一些钩子函数(后边可能会深入学习吧),这里就不深入学习目录中的文件作用了。

2. 检查文件状态

2.1 命令说明

我们可以用 git status 命令查看哪些文件处于什么状态。 如果在克隆仓库后立即使用此命令,会看到类似这样的输出:

image-20230622085514421

这说明我们现在的工作目录相当干净。换句话说,所有已跟踪文件在上次提交后都未被更改过。 此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪状态的新文件,否则 Git 会在这里列出来。 最后,该命令还显示了当前所在分支,分支名是“master”,这是默认的分支名。

我们先创建一个新的文件,不做任何操作,使用该命令,发现 Git 已经检测到该文件,当文件还未被提交到暂存区的时候显示为红色

image-20230622085527957

在状态报告中可以看到新建的 README 文件出现在 Untracked files 下面。 未跟踪的文件意味着 Git 在之前的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非我们明明白白地告诉它“我需要跟踪该文件”。 这样的处理让我们不必担心将生成的二进制文件或其它不想被跟踪的文件包含进来。 不过现在的例子中,我们确实想要跟踪管理 README 这个文件。

2.2 简介的输出

git status 命令的输出十分详细,但输出有些繁琐。 Git 有一个选项可以缩短状态命令的输出,这样可以以简洁的方式查看更改,如下所示:

1
2
git status -s       # 使用该命令查看状态
git status --short # 或者使用该命令
image-20230622085700880

可以看到文件前边有两个?号,后百年我们还可能会看到一些其他的符号,在这里总结如下:

标记 说明
?? 新添加的未跟踪文件(红色)
A 新添加到暂存区中的文件(绿色)
M 修改过的文件(红色)
AM 已添加到暂存区的文件又被修改了(A绿色,M红色)
UU 由合并分支引起冲突,修改文件后还未添加到暂存区的状态标记(红色)
R 文件被重命名了

3. 跟踪新文件

3.1 命令说明

跟踪文件就是把文件添加到暂存区.表示当前目录下所有文件,也可以只管理某一个文件,后边换成文件名称即可。

1
2
git add .            # 添加所有文件
git add <file_name> # 添加指定文件,可以同时指定多个文件

3.2 使用实例

使用命令 git add 开始跟踪一个文件。 所以,要跟踪 README 文件,运行:

1
git add README.md

此时再运行 git status 命令,会看到 README 文件已被跟踪,并处于暂存状态:

image-20230622090416237

只要在 Changes to be committed 这行下面的,就说明是已暂存状态。 如果此时提交,那么该文件在我们运行 git add 时的版本将被留存在后续的历史记录中。 你可能会想起之前我们使用 git init 后就运行了 git add <files> 命令,开始跟踪当前目录下的文件。 git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。

4. 提交更新

4.1 命令格式

现在的暂存区已经准备就绪,可以提交了,提交是提交到哪里?当然是提交到本地的版本库中了。 在此之前,我们需要确认还有什么已修改或新建的文件还没有 git add 过, 否则提交的时候不会记录这些尚未暂存的变化。 这些已修改但未暂存的文件只会保留在本地磁盘。 所以,每次准备提交前,先用 git status 看下,我们所需要的文件是不是都已暂存起来了, 然后再运行提交命令 git commit

1
git commit -m "提交说明"

-m参数用于指定提交说明,但是我们也可以不用-m参数,只执行git commit的话,Git会启动我们选择的文本编辑器来输入提交说明(启动的编辑器是通过 Shell 的环境变量 EDITOR 指定的,一般为 vim 或 emacs。 当然也可以按照 起步 介绍的方式, 使用 git config --global core.editor 命令设置我们喜欢的编辑器)。会显示什么?后边实例中有。

4.2 使用实例

我们提交一下刚才创建的README.md文件:

1
git commit

执行完此命令后,编辑器会显示类似下面的文本信息(选用 Vim 的屏显方式展示):

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: README.md
#
~
~ .git/COMMIT_EDITMSG [unix] (10:30 22/06/2023) 1,0-1 全部
"/d/git_test/.git/COMMIT_EDITMSG" [unix] 11L, 231B

可以看到,默认的提交消息包含最后一次运行 git status 的输出,放在注释行里,另外开头还有一个空行,供我们输入提交说明。 我们完全可以去掉这些注释行,不过留着也没关系,多少能帮我们回想起这次更新的内容有哪些。退出编辑器时,Git 会丢弃注释行,用我们输入的提交说明生成一次提交。

当我们保存退出后,已经创建了第一个提交:

image-20230622103511817

可以看到,提交后它会告诉我们,当前是在哪个分支(master)提交的,本次提交的完整 SHA-1 校验和是什么(4a96757),以及在本次提交中,有多少文件修订过,多少行添加和删改过。

需要知道的是,提交时记录的是放在暂存区域的快照。 任何还未暂存文件的仍然保持已修改状态,可以在下次提交时纳入版本管理。 每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。

5. 暂存已修改的文件

5.1 修改文件并查看状态

上边我们已经暂存了README.md文件并且提交,接下来我们修改这个文件,在文件内随便写点内容即可:

image-20230622103856496

然后我们再看一下文件状态:

image-20230622103928199

我们发现,修改后在 Changes not staged for commit 这行下面出现了信息,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。

5.2 提交到暂存区

现在让我们运行 git add 将“README.md”放到暂存区,然后再看看 git status 的输出:

image-20230622104017994

我们发现README.md文件变成了Modified的状态,加上-s选项后,前边的标识变为了M。下次提交时就会一并记录到仓库。

5.3 又修改了文件?

假设此时,我们还没有将暂存区的文件提交到版本库,但是想要在 README.md 里再加条注释。 可以看下边的图,VS Code中会直接列出我们相对于上一次提交所做的更改,这丫就是为什么我选择在Windows中使用VS Code来学习Git的原因。当然,VS Code也可以在linux中使用,也是一样的操作,只是在Windows下方便一些罢了。

image-20230622104530531

重新编辑存盘后,准备好提交。我们此时再运行 git status 看看:

image-20230622104755961

现在 README.md 文件同时出现在暂存区和非暂存区。 这怎么可能呢? 实际上 Git 只不过暂存了我们运行 git add 命令时的版本。 如果我们现在提交,README.md 的版本是我们最后一次运行 git add 命令时的那个版本,而不是我们运行 git commit 时,在工作目录中的当前版本。 所以,运行了 git add 之后又作了修订的文件,需要重新运行 git add 把最新版本重新暂存起来:

image-20230622104923735

5.4 提交修改的文件

为了方便后边测试,这里对修改后的文件进行一次提交:

1
git commit -m "feat:第二次提交README.md文件(添加了一些内容)"
image-20230622105148594

6. 跳过使用暂存区域

6.1 命令格式

尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。 Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:

1
git commit -a

6.2 使用实例

我们修改一下 README.md 文件,然后直接跳过暂存区域提交:

image-20230622160633558

7. 移除文件

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。

7.1 命令格式

我们可以通过git rm命令来移除文件,它可以带参数,以达到不同的效果:

1
2
git rm <file_name>          # 移除文件并连带从工作目录中删除指定的文件(会直接删除磁盘上的文件)
git rm --cached <file_name> # 移除文件但不从工作目录中删除指定的文件(不会会直接删除磁盘上的文件)

这两个命令其实更都会执行两个步骤:

(1)将指定的文件从暂存库移除;

(2)使用git add进行一次提交,将改动提交到暂存库。

不同之处就是,前者会将文件直接从磁盘删除,后者不会,后者移除的文件会在git仓库中变成未跟踪状态。另外就是如果是要移除目录的跟踪的话,好像还需要加上-r参数。

7.2 使用实例

7.2.1 移除并删除

1
git rm README.md

移除之后我们可以查看一下文件状态:

image-20230622161247987

会发现这个文件被删除了,另外看一下磁盘上,这个文件也消失了。注意,这里可以看到删除的信息出现在Changes not staged for commit后边吗,这就意味着,该命令把文件删了之后,还把文件的该动提交到暂存区,但是还没有提交到版本库。

7.2.2 移除但不删除

额,上边把文件删了,需要先恢复一下,提前用一个撤销命令:

1
2
git reset HEAD README.md  # 撤销git add 操作
git checkout -- README.md # 撤销删除操作

然后我们执行git rm的时候加上--cached

1
git rm --cached README.md

移除之后我们看一下文件的状态:

image-20230622162152785

可以发现,这个文件变成了未跟踪状态,并且从暂存库中删除了这个文件,还产生了一次git add操作。

7.3 glob 模式

glob 模式也就是git rm命令后边可以使用正则表达式,例如

1
git rm log/\*.log

注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:

1
git rm \*~

该命令会删除所有名字以 ~ 结尾的文件。

7.4 撤销修改

由于还要使用这个README.md文件,还是要提前用一下后边的一些撤销命令来撤销移除文件的相关操作:

1
2
git reset HEAD README.md  # 撤销git add 操作
git checkout -- README.md # 撤销删除操作

8. 移动文件

不像其它的 VCS 系统,Git 并不显式跟踪文件移动操作。 如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。 不过 Git 非常聪明,它会推断出究竟发生了什么,至于具体是如何做到的,我们稍后再看。

8.1 命令格式

我们可以直接使用mv命令来移动或者重命名文件,但是要加上git,例如, 要在 Git 中对文件改名,可以这么做:

1
git mv src_name dst_name

8.2 使用实例

我们将README.md文件改名为README:

1
git mv README.md README

我们查看一下文件状态,如下所示:

image-20230622163200920

其实,运行 git mv 就相当于运行了下面三条命令:

1
2
3
mv README.md README
git rm README.md
git add README

如此分开操作,Git 也会意识到这是一次重命名,所以不管何种方式结果都一样。 两者唯一的区别在于,git mv 是一条命令而非三条命令,直接使用 git mv 方便得多。 不过在使用其他工具重命名文件时,记得在提交前 git rm 删除旧文件名,再 git add 添加新文件名。

三、查看帮助文档

1. 查询方式

Git其实也为我们提供了帮助文档,我们可以使用下边的命令打开指定命令的说明:

1
git -h <command>

command表示命令。

2. 使用实例

例如我们现在想查一下add命令的用法,就可以执行:

1
git -h add

然后就会在浏览器打开本地的说明文档,里边将包含add命令的详细说明:

image-20230623142305380