Git学习(三)

0x00 前言

前两天学习了
Git学习(二)
Git学习(一)

今天接着学习Git的管理修改、撤销修改和删除文件。

0x01 管理修改

Git如此优秀是因为Git跟踪管理的是修改而不是文件。

那么什么是修改呢? 比如新增一行,删除一行,更改了某些字符,都是修改,创建一个文件,删除一个文件,都是修改。

为什么说Git管理的是修改而不是文件呢?我们接着看。

首先对README.txt进行修改,添加一行:

1
2
3
4
Git is a version control system.
This is my first test for Git!
Git is so good!
Git管理的是修改

git add

1
2
3
4
5
6
7
8
$ git add README.txt

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

modified: README.txt

再对README.txt进行修改:

1
2
3
4
5
6
$ cat README.txt
Git is a version control system.
This is my first test for Git!
Git is so good!
Git管理的是修改
test test test

使用git commit提交,再查看状态

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git commit -m "modify README.txt"
[master 9f9c092] modify README.txt
1 file changed, 1 insertion(+)

$ 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: README.txt

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

可以看到,我们第二次修改并没有被提交。

Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

我们可以使用git diff HEAD -- README.txt查看一下工作区和版本库的区别。

1
2
3
4
5
6
7
8
9
10
$ git diff HEAD -- README.txt
diff --git a/README.txt b/README.txt
index f9b34f5..56dbf91 100644
--- a/README.txt
+++ b/README.txt
@@ -2,3 +2,4 @@ Git is a version control system.
This is my first test for Git!
Git is so good!
Git管理的是修改
+test test test

可见,第二次的修改确实没有被提交。

0x02 撤销修改

如果你在写报告的时候,不小心写错了,例如,再README.txt中添加一行:

1
2
3
4
5
6
7
$ cat README.txt
Git is a version control system.
This is my first test for Git!
Git is so good!
Git管理的是修改
test test test
It is wrong!

在你要准备提交的时候,你突然发现了这个错误,幸亏发现的及时

1
2
3
4
5
6
7
8
9
$ 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: README.txt

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

我们可以发现,Git给了我们提示,git checkout -- file可以丢弃工作区的修改

1
git checkout -- README.txt

这样就可以把对README.txt文件在工作区的修改全部撤销,这个时候有两种情况:

第一种: README.txt在被修改后还没有被添加到暂存区,这样只要执行上面的命令就可以回到和版本库一样的状态

第二种: README.txt修改后已经被添加到暂存区,之后又做了修改,这样撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

git checkout -- file命令中的--很重要,没有--,就变成了切换分支的意思。

假如你写错了一些东西,而且还git add到了暂存区,但是还没有git commit

1
2
3
4
5
6
7
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: README.txt

Git告诉我们,使用git reset HEAD <file>命令可以把暂存区的修改撤销(unstage),重新回到工作区

1
2
3
$ git reset HEAD README.txt
Unstaged changes after reset:
M README.txt

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。

回到工作区之后,再使用上面的丢弃工作区的修改即可。

0x03 删除文件

在Git中,删除也是一个修改操作,我们测试一下。

首先添加一个test.txt,并提交。

1
2
3
4
$ git commit -m "add test.txt"
[master 2a4c645] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt

一般情况下,我们直接把工作区的文件删除即可

这个时候,Git知道我们删除了这个文件,这样工作区和版本库就不一样了,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 checkout -- <file>..." to discard changes in working directory)

deleted: test.txt

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

现在我们有两个选择,一是我们就是要从版本库中删除该文件,那就用git rm <file>命令删除,然后再git commit`:

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

$ git commit -m "remove test.txt"
[master b2f143d] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt

这样,该文件就从版本库中删除了。

二是我们误删了该文件,想要恢复,怎么办呢?
因为版本库里还有该文件,所以我们可以轻松的把误删的文件恢复到最新版本。

1
git checkout -- text.txt

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

0x04 总结

  1. Git跟踪的是修改,而不是文件,每次修改,如果没有用git add添加到暂存区,那就不会被commit到版本库中。

    • ①当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时, 用命令git checkout -- file
    • 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,就回到了①,第二步按①操作。
    • 已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
  2. 已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。