作者:下里巴人

来自南京审计大学

工作区和暂存区

工作区

在我们之前的操作中,工作区就指的是learngit文件夹。

版本库

工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

正如我们之前所讲,我们提交文件一共分两步:

  • git add命令是将文件修改添加到暂存区。
  • git commit命令是把暂存区的所有内容提交到当前分支

操作演示

我们首先对readme.txt做一个修改,如下:

1
2
3
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.

紧接着,我们在工作区新建一个文本文件LICENSE,内容随意,接着我们来查看一下暂存区状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git status

On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt

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

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

Git非常清楚地告诉我们,readme.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked。现在,使用两次命令git add,把readme.txtLICENSE都添加后,用git status再查看一下:

1
2
3
4
5
6
7
8
9
10
$ git add readme.txt
$ git add LICENSE.txt
$ git status

On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

new file: LICENSE
modified: readme.txt

现在,暂存区的状态就变成这样了:

所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支:

1
2
3
4
5
$ git commit -m"understand how stage works"

[master 46d9aa2] understand how stage works
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 LICENSE.txt

紧接着,如果我们检查一下缓存区状态:

1
2
3
4
$ git status

On branch master
nothing to commit, working tree clean

此时我们的工作区是非常干净的,现在版本库变成了这样,暂存区就没有任何内容了:

查看工作区和版本库里面最新版本的区别

我们先将readme.txt修改如下,但是不提交:

1
2
3
4
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git nononono

这时我们可以发现,我们现在工作区的文件应该与库中的最新版本不一致,那我们如何看到区别呢?我们可以输入以下指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git diff HEAD -- readme.txt

diff --git a/readme.txt b/readme.txt
index f21047c..7df0f53 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,3 +1,4 @@
Git is a distributed version control system.
Git is free software distributed under the GPL.
-Git has a mutable index called stage.
\ No newline at end of file
+Git has a mutable index called stage.
+Git nononono
\ No newline at end of file

撤销修改

我们在修改文件的时候,不可避免的会出现一些失误,分为很多种情况,那我们该怎么撤销我们修改呢?,方法如下:

1
2
3
4
5
6
$ git restore file

$ git restore --staged file

$ git reset --hard HEAD^

情况1:在工作区做了修改,并未添加到暂存区,想撤销工作区的修改,用 git restore file;

情况2:在工作区做了修改,并用git add 添加到了暂存区,未提交;想撤销,分两步,1.先撤销暂存区的修改,用 git restore –staged file, 2.然后参考情况1撤销工作区的修改;

情况3:在工作区做了修改,且git add git commit添加并提交了内容,想撤销本次提交,直接用 git reset –hard HEAD^回退版本,即可保证工作区,暂存区,版本库都是上次的内容.

删除文件

删除工作区文件

我们首先在工作区新建文件test.txt这个操作很简单,你可以就像平常删除文件一般,右击删除。当人,也可以使用如下指令:

1
$ rm test.txt

这时,使用git status查看工作区状态,会立刻告诉你哪些文件被删除了:

1
2
3
4
5
6
7
8
9
$ git status

On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: test.txt

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

撤销删除工作区文件

如果这时你发现你是误删,别急,你可以输入以下指令来恢复改文件:

1
git restore -- test.txt

注意!!其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
但是,从来没有被添加到版本库就被删除的文件,是无法恢复的!

删除版本库中的改文件

如果你在删除工作区文件中,你也确实要删除版本库中的该文件,需要连续使用以下两个指令:

1
2
3
4
5
6
7
8
$ git rm test.txt
rm 'test.txt'

$ git commit -m "remove test.txt"

[master d46f35e] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt

如何撤销已经提交到暂存区的删除?

当你使用git rm test.txt命令后,你突然后悔,想要恢复,这时你输入:

1
2
3
$ git restore -- test.txt

error: pathspec 'test.txt' did not match any file(s) known to git

git rm test.txt 相当于是删除工作目录中的test.txt文件,并把此次删除操作提交到了暂存区

使用git restore – test.txt相当于是让工作目录test.txt恢复到暂存区中test.txt的状态,

但是工作目录中test.txt已经被删除,无法找到文件来再次删除所以报错。

所以这时,我们应该如下操作:

1
2
3
4
5
6
$ git reset head test.txt

Unstaged changes after reset:
D test.txt

$ git restore -- test.txt

必须先使用git reset head test.txt在暂存区中将删除操作丢弃,

然后在git restore – test.txt就是直接将工作目录中test.txt恢复到版本库中的状态.