git学习2 -时光穿梭
修改文本文件、git status、git diff
文件修改后,使用git status
查看:
$ cat readme.txt
Git is a version control system.
Git is free software.
$ vim readme.txt
$ cat readme.txt
Git is a distributed version control system.
Git is free software.
add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$ 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: .idea/.gitignore
modified: .idea/misc.xml
modified: .idea/modules.xml
modified: .idea/pycharm_project.iml
modified: main.py
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
.idea/vcs.xml
no changes added to commit (use "git add" and/or "git commit -a")
$
git status
命令可以让我们时刻掌握仓库当前的状态,上面的命令输出告诉我们,readme.txt
被修改过了,但还没有准备提交的修改。
虽然git告诉我们readme.txt
被修改了,但如果能看看具体修改了什么内容,自然是很好的。比如你休假回来,第一天上班时,已经记不清上次怎么修改的readme.txt
,用git diff
这个命令看看:
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index ec548e1..773c4ec 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,3 +1,4 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
+add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$
git diff
顾名思义就是查看difference,显示的格式正是Unix通用的diff格式,可以从上面的命令输出看到,我们在第一行添加了一个distributed
单词。
这里区别不太直观,可以用图形化的工具查看变化,比如pycharm。
修改文件后git add、git commit
知道了对readme.txt
作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步。
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .idea/vcs.xml
modified: readme.txt
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: .idea/.gitignore
modified: .idea/misc.xml
modified: .idea/modules.xml
modified: .idea/pycharm_project.iml
modified: .idea/vcs.xml
modified: main.py
$ git commit -m "add distributed etc. in readme.txt"
[master 23c8bbe] add distributed etc. in readme.txt
2 files changed, 8 insertions(+), 1 deletion(-)
create mode 100644 .idea/vcs.xml
$ 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: .idea/.gitignore
modified: .idea/misc.xml
modified: .idea/modules.xml
modified: .idea/pycharm_project.iml
modified: .idea/vcs.xml
modified: main.py
no changes added to commit (use "git add" and/or "git commit -a")
$
小结下上面的内容:
graph TD D[modified] --> A[git status: Changes not staged for commit] A --> E[git diff file] A --> |git add files| B(git status: Changes to be committed) B --> |git commit -m messages| C(no changes added to commit)将其他修改的文件add到暂存区,并commit.
$ 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: .idea/.gitignore
modified: .idea/misc.xml
modified: .idea/modules.xml
modified: .idea/pycharm_project.iml
modified: .idea/vcs.xml
modified: main.py
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: .idea/.gitignore
modified: .idea/misc.xml
modified: .idea/modules.xml
modified: .idea/pycharm_project.iml
modified: .idea/vcs.xml
modified: main.py
$ git commit -m "other files"
[master 6e4be35] other files
6 files changed, 41 insertions(+), 41 deletions(-)
$ git status
On branch master
nothing to commit, working tree clean
$
每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit
。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
再修改一次,重复上面的过程。
$ vim readme.txt
$ 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
no changes added to commit (use "git add" and/or "git commit -a")
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 773c4ec..0280963 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
Git is a distributed version control system.
-Git is free software.
+Git is free software distributed under the GPL.
add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: readme.txt
$ git commit -m "modified readme.txt 3rd times"
[master 5036f8a] modified readme.txt 3rd times
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working tree clean
$
PyCharm里比较当前版本与上一版本文件的差异:
git log、版本号
历史记录查看使用git log
命令显示从最近到最远的提交日志,我们可以看到4次提交。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline
参数
$ git log
commit 5036f8a34e290a4c0a4c163cf6aaeb6fdd7dc2fe (HEAD -> master)
Author: carysunqd <carys@aliyun.com>
Date: Thu Apr 15 14:31:47 2021 +0800
modified readme.txt 3rd times
commit 6e4be35b62803e1235a0fdea1cd07f304c953a41
Author: carysunqd <carys@aliyun.com>
Date: Thu Apr 15 14:18:54 2021 +0800
other files
commit 23c8bbec00110cf30b766d217ee3dbfb87dfe989
Author: carysunqd <carys@aliyun.com>
Date: Thu Apr 15 13:39:33 2021 +0800
add distributed etc. in readme.txt
commit 82a5f16e1fc3c9301ddaac424376373514d60b89
Author: carysunqd <carys@aliyun.com>
Date: Thu Apr 15 11:17:40 2021 +0800
wrote a readme file
commit 0ea41b70b1c3dd1c6879df54e90ad2473e53187f
Author: carysunqd <carys@aliyun.com>
Date: Wed Apr 14 17:47:10 2021 +0800
Initial Commit
$ git log --pretty=oneline
5036f8a34e290a4c0a4c163cf6aaeb6fdd7dc2fe (HEAD -> master) modified readme.txt 3rd times
6e4be35b62803e1235a0fdea1cd07f304c953a41 other files
23c8bbec00110cf30b766d217ee3dbfb87dfe989 add distributed etc. in readme.txt
82a5f16e1fc3c9301ddaac424376373514d60b89 wrote a readme file
0ea41b70b1c3dd1c6879df54e90ad2473e53187f Initial Commit
$
看到的一大串类似5036f8a34e290a4c0a4c163cf6aaeb6fdd7dc2fe
的是commit id
(版本号),和SVN不一样,Git的commit id
不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id
和我的肯定不一样。为什么commit id
需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:
git reset --hard、HEAD^、HEAD^^、HEAD~100
启动时光穿梭机,准备把readme.txt
回退到上一个版本,也就是other files
的那个版本。
首先,Git必须知道当前版本是哪个版本,在Git中HEAD
表示当前版本,也就是最新的提交5036f8a34e290a4c0a4c163cf6aaeb6fdd7dc2fe
,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
现在,我们要把当前版本modified readme.txt 3rd times
回退到上一个版本other files
,就可以使用git reset
命令:
$ git reset --hard HEAD^
HEAD is now at 6e4be35 other files
$ cat readme.txt
Git is a distributed version control system.
Git is free software.
add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$ git log --pretty=oneline
6e4be35b62803e1235a0fdea1cd07f304c953a41 (HEAD -> master) other files
23c8bbec00110cf30b766d217ee3dbfb87dfe989 add distributed etc. in readme.txt
82a5f16e1fc3c9301ddaac424376373514d60b89 wrote a readme file
0ea41b70b1c3dd1c6879df54e90ad2473e53187f Initial Commit
$
--hard
参数有啥意义?这个后面再讲,现在你先放心使用。
看看readme.txt
的内容已经改回之前的版本了。
最新的那个版本modified readme.txt 3rd times
已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?
办法其实还是有的,只要上面的命令行窗口还没有被关掉(您记录下了回退前的版本号),找到那个modified readme.txt 3rd times
的commit id
是5036f8...
,于是就可以指定回到未来的某个版本。命令里版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。:
$ git reset --hard 5036f8
HEAD is now at 5036f8a modified readme.txt 3rd times
$ git log --pretty=oneline
5036f8a34e290a4c0a4c163cf6aaeb6fdd7dc2fe (HEAD -> master) modified readme.txt 3rd times
6e4be35b62803e1235a0fdea1cd07f304c953a41 other files
23c8bbec00110cf30b766d217ee3dbfb87dfe989 add distributed etc. in readme.txt
82a5f16e1fc3c9301ddaac424376373514d60b89 wrote a readme file
0ea41b70b1c3dd1c6879df54e90ad2473e53187f Initial Commit
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
add 日本官员称核废水"喝了没事" 赵立坚:请他喝了再说
$
HEAD指针
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD从指向modified readme.txt 3rd times
:
┌────┐
│HEAD│
└────┘
│
└──> ○ modified readme.txt 3rd times
│
○ other files
│
○ add distributed etc. in readme.txt
│
○ wrote a readme file
改为指向other files
:
┌────┐
│HEAD│
└────┘
│
| ○ modified readme.txt 3rd times
| │
└──> ○ other files
│
○ add distributed etc. in readme.txt
│
○ wrote a readme file
就把工作区的文件更新了。所以你让HEAD
指向哪个版本号,你就把当前版本定位在哪。
git reflog
如果回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^
回退到other files
版本时,再想恢复到modified readme.txt 3rd times
,就必须找到modified readme.txt 3rd times
的commit id。Git提供了一个命令git reflog
用来记录你的每一次命令:
$ git reflog
5036f8a (HEAD -> master) HEAD@{0}: reset: moving to 5036f8
6e4be35 HEAD@{1}: reset: moving to HEAD^
5036f8a (HEAD -> master) HEAD@{2}: commit: modified readme.txt 3rd times
6e4be35 HEAD@{3}: commit: other files
23c8bbe HEAD@{4}: commit: add distributed etc. in readme.txt
82a5f16 HEAD@{5}: commit: wrote a readme file
0ea41b7 HEAD@{6}: commit (initial): Initial Commit
$
总结
-
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。 - 穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。