增删查改
但我们每次修改文件的时候,我们可以使用 git add 加上文件的名字,将文件加入版本库,然后再使用 git commit 提交修改。假设我们在版本库中创建了三个新的文件file1.txt,file2.txt,file3.txt,那我们我们可以使用以下的命令更新版本库:
$ git add file1.txt file2.txt file3.txt
$ git commit -m "Added three new files"
除了使用第一行的方式添加多个文件,我们可以使用git add .(英文句号)将当前所有有变化的文件加入版本库:
$ git add .
Git记录 (log)
在git中,每一次提交修改(commit),这条记录都会被保存起来。好比建大楼的时候,每个commit记录了盖楼需要添加和拿走的材料,这个施工过程都被记录下来了。而在git中,使用git log就能查看代码改动信息。
基于我们之前对版本库的改动,我们使用git log就能看的以下的信息,其中包含了commit ID、作者(修改者)、日期和修改备注:
commit 2443b8c95bd2f426447b76b77ad5385a3d79a4ea (HEAD -> master)
Author: Enoch <[email protected]>
Date: Thu Oct 17 08:06:30 2019 -0700
Added three new files
commit f76e81f3c8e7c54dd917e9616da64ff3fde4fab9
Author: Enoch <[email protected]>
Date: Mon Oct 14 09:44:19 2019 -0700
Modified the first two lines of new file
commit 2bbcd42eb3441375ae8f3c0b15d3f776302ad4fe
Author: Enoch <[email protected]>
Date: Mon Oct 14 09:32:28 2019 -0700
Added a new file
如果这个时候我们在file1.txt的内部添加以下内容:
new content
然后我们再使用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: file1.txt
no changes added to commit (use "git add" and/or "git commit -a")
那我们就先将此改动添加(add)并提交(commit)到版本库:
$ git add file1.txt
$ git commit -m "Modified file1"
[master 0e84b3e] Modified file1
1 file changed, 1 insertion(+)
这个时候我们再查看log,则会发现我们多了一条commit:
commit 0e84b3e405630f1fc6ca9beb82cf5ca9ed38ea5a (HEAD -> master)
Author: Enoch <[email protected]>
Date: Thu Oct 17 08:21:19 2019 -0700
Modified file1
commit 2443b8c95bd2f426447b76b77ad5385a3d79a4ea
Author: Enoch <[email protected]>
Date: Thu Oct 17 08:06:30 2019 -0700
Added three new files
...
Working directory, Staging area, Repository
为了帮助大家更好的理解工作区(working directory)、暂存区(staging directory)、和版本库(repository),我们可以对各个区域进行修改,然后通过git diff来查看他们之间的区别。
比如我们先给file2.txt添加以下的内容:
new content in file2
入行我们使用git diff来对比当前的工作区和上一次commit的版本库的区别:
$ git diff
diff --git a/file2.txt b/file2.txt
index e69de29..de59346 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,0 +1 @@
+new content in file2
如果这个时候我们使用add file2的修改,将当前的改动添加到暂存区,那么我们使用git diff后,会发现没有任何信息,这是因为我们的改动被转移到暂且区了。所以我们可以使用diff加上–cached来对比当前的暂存区和上一个commit的区别:
$ git diff --cached
diff --git a/file2.txt b/file2.txt
index e69de29..de59346 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,0 +1 @@
+new content in file2
我们可以再改动一下file3.txt,在其中添加以下内容:
new content in file3
我们可以使用git diff HEAD来对比当前暂且区和工作区的区别:
diff --git a/file2.txt b/file2.txt
index e69de29..de59346 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,0 +1 @@
+new content in file2
diff --git a/file3.txt b/file3.txt
index e69de29..944ef83 100644
--- a/file3.txt
+++ b/file3.txt
@@ -0,0 +1 @@
+new content in file3
这个时候我们将三个区间的内容进行对比,大家就能理解三个区间的关系了:
$ git diff
diff --git a/file3.txt b/file3.txt
index e69de29..944ef83 100644
--- a/file3.txt
+++ b/file3.txt
@@ -0,0 +1 @@
+new content in file3
$ git diff --cached
diff --git a/file2.txt b/file2.txt
index e69de29..de59346 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,0 +1 @@
+new content in file2
$ git diff HEAD
diff --git a/file2.txt b/file2.txt
index e69de29..de59346 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,0 +1 @@
+new content in file2
diff --git a/file3.txt b/file3.txt
index e69de29..944ef83 100644
--- a/file3.txt
+++ b/file3.txt
@@ -0,0 +1 @@
+new content in file3
但我们确定要修改的内容后,我们可以直接add并commit,将所有的修改加到暂存区后并提交到版本库:
$ git add .
$ git commit -m "Modified file2 and file3"
[master 0aef827] Modified file2 and file3
2 files changed, 2 insertions(+)
时光穿越机 (checkout & reset)
有时候我们对一些文件做了改动,并加到暂存区,但是又后悔了,这些操作在 git 中也能实现。比如,我们继续改动file1.txt,在其中添加一行的内容:
new content
more content
然后我们把file1.txt加入暂存区,如果我们想要反悔,可以直接使用 git reset 把 file1.txt 从暂存区拉回到工作区,然后对文件做相应的修改后再add:
$ git add file1.txt
$ git status -s
M file1.txt # working directory
$ git reset file1.txt
Unstaged changes after reset:
M file1.txt
$ git status -s
M file1.txt # staging area
然后我们把file1.txt中第一行new content删除,只剩下more content之后,直接add然后commit:
$ git add file1.txt
$ git commit -m "Added more content in file1"
接下来我们来了解git中的checkout,checkout可以帮助我们让当前的工作区回到特定的某个commit,比如我们使用git log查看过去的一些commit:
$ git log --oneline
5c10f81 (HEAD -> master) Added more content in file1
0aef827 Modified file2 and file3
0e84b3e Modified file1
2443b8c Added three new files
f76e81f Modified the first two lines of new file
2bbcd42 Added a new file
然后我们使用checkout回到 0aef827 这个commit,可以发现 file1.txt 的内容也变回了,因为在那个时候 file1 的内容并没有被改动,所以我们用了git log之后并没有 Added more content in file1 这个commit:
$ git checkout 0aef827
Note: checking out '0aef827'.
....
$ cat file1.txt
new content
$ git log --oneline
0aef827 (HEAD) Modified file2 and file3
0e84b3e Modified file1
2443b8c Added three new files
f76e81f Modified the first two lines of new file
2bbcd42 Added a new file
若想要在从过去回到现在,我们可以使用 git checkout master:
$ git checkout master
$ cat file1.txt
more content
我们可以通过下面的图片对checkout进行理解:
这里的HEAD其实是一个指针,可以让我们知道当前处于哪一个commit。如果我们想要让HEAD彻底回到某一个commit,我们可以使用在reset后面加上–hard参数:
$ git reset --hard HEAD # 当前add的工作全部消失,回到上一次commit
HEAD is now at 5c10f81 Added more content in file1
$ git log --oneline
5c10f81 (HEAD -> master) Added more content in file1
0aef827 Modified file2 and file3
0e84b3e Modified file1
...
$ git reset --hard HEAD^ # 回到当前master的上一个commit:c0aef827
$ git reset --hard 0e84b3e # 回到具体的某一个commit
$ git log --oneline
0e84b3e (HEAD -> master) Modified file1
2443b8c Added three new files
f76e81f Modified the first two lines of new file
2bbcd42 Added a new file
我们的 Modified file2 and file3 彻底消失了!如果我们想要重新挽回改动,可以使用 git reflog 查看最近做的所有的 HEAD 的改动,并使用 reset 重回到想要退回的 commit:
$ git reflog
0e84b3e (HEAD -> master) HEAD@{0}: reset: moving to 0e84b3e
0aef827 HEAD@{1}: reset: moving to HEAD^
5c10f81 HEAD@{2}: reset: moving to HEAD
5c10f81 HEAD@{3}: checkout: moving from 0aef8274ff89375120cbd38be7e4a494aa19f0e7 to master
0aef827 HEAD@{4}: checkout: moving from master to 0aef827
5c10f81 HEAD@{5}: commit: Added more content in file1
...
$ git reset --hard 5c10f81
通过查看 file1.txt 的内容,确定一下我们时空穿越成功:
$ git cat file1.txt
more content
实践练习
在第一个实践练习创建的版本库new_dir中,为file.txt添加一行内容 new random information,然后添加并提交新的commit。然后使用git reset将当前版本库退回至上一个commit,完成操作后,请确定file.txt又变成了空文件夹。