git学习2 -时光穿梭

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学习2 -时光穿梭

修改文件后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学习2 -时光穿梭

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学习2 -时光穿梭

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 timescommit id5036f8...,于是就可以指定回到未来的某个版本。命令里版本号没必要写全,前几位就可以了,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查看命令历史,以便确定要回到未来的哪个版本。
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] C --> |git log --pretty=oneline| F(从最近到最远的提交日志) C --> |git reflog| H(每一次的提交记录) C --> |git reset --hard| G[回退到历史或未来版本]
上一篇:浏览器缓存策略


下一篇:前端缓存之HTTP缓存