0%

Mosh的Git课程笔记(3)--Browsing History

Mosh的课程网址

Viewing the History

基本命令:

1
$ git log

用 —oneline 查看简略信息,—stat 显示每个文件增删的行数:

1
$ git log --oneline --stat

—patch 查看每个文件具体的内容更改:

1
$ git log --oneline --patch

Filtering the History

用 -3 表示只查看前三条历史commit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ git log --oneline
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 Initial commit
3fd1e3e Remove unused code
b184de1 Remove unused code
dd03e4e Fix the bug
3b634ca add Lines
a787fca add line
568c0fc Initial commit.

$ git log --oneline -3
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js

用 author 名字过滤:

1
$ git log --oneline --author="Stone"

用时间过滤:

1
2
3
$ git log --oneline --after="2021-04-21"
$ git log --oneline --after="yesterday"
$ git log --oneline --after="one week ago"

用 commit 时的 message 过滤:

1
2
3
4
5
$ git log --oneline --grep="add"
fdb7fb6 add data
62416e2 add files
3b634ca add Lines
a787fca add line

用具体更改的内容过滤:

1
2
3
4
5
6
7
8
9
10
11
$ git log --oneline -S"world" --patch
0f62ff0 remove all js files
diff --git a/file1.js b/file1.js
deleted file mode 100644
index 29887f9..0000000
--- a/file1.js
+++ /dev/null
@@ -1,3 +0,0 @@
-hello world
-sky
-sun

根据 ID 选取某区间的 commit 历史:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ git log --oneline
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js //----------到此为止--------------
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data
62416e2 add files //---------从这上一行往上-----------
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 Initial commit
3fd1e3e Remove unused code
b184de1 Remove unused code
dd03e4e Fix the bug
3b634ca add Lines
a787fca add line
568c0fc Initial commit.

$ git log --oneline 62416e2..9b82d1b
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data

查看某个文件的修改 commit 历史:

1
2
3
4
5
6
7
8
9
10
11
$ git log --oneline file1.js
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data
62416e2 add files
fde6777 modified
f264740 modified

如果报错说不清楚,就在文件名之前加—

1
$ git log --oneline -- file1.js

查看该文件的具体内容修改:

1
$ git log --oneline --patch -- file1.js

Formatting the Log Output

调整 log 格式

1
$ git log --pretty=format:"%Cgreen%an%Creset committed %h on %cd"

3_01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
%Cgreen
switch color to green

%an
author name

%Creset
reset color

%H
commit hash

%h
abbreviated commit hash

%cd
committer date (format respects --date= option)

Creating Aliases

给加格式的 log 命令起个别名:

1
$ git config --global alias.lg "log --pretty=format:'%an committed %h'"

就可以方便地使用啦:

1
2
3
4
5
$ git lg
Stone committed d7d9bfb
Stone committed d2acf0e
Stone committed 9b82d1b
Stone committed 78daaab

起别名的另一个例子:

1
2
3
$ git config --global alias.unstage "restore --staged ."

$ git unstage

Viewing a Commit

查看详细信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git show HEAD~2
commit 9b82d1b30e0ea17c2a63732ede1652f7ad0da29b
Author: Stone <masaike@qq.com>
Date: Thu Apr 22 19:04:57 2021 +0800

Add file1.js

diff --git a/file1.js b/file1.js
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/file1.js
@@ -0,0 +1 @@
+hello

查看该commit版本的某文件的具体内容:

1
2
$ git show HEAD~2:file1.js
hello

查看简略信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ git show HEAD~2 --name-only
commit 9b82d1b30e0ea17c2a63732ede1652f7ad0da29b
Author: Stone <masaike@qq.com>
Date: Thu Apr 22 19:04:57 2021 +0800

Add file1.js

file1.js

$ git show HEAD~2 --name-status
commit 9b82d1b30e0ea17c2a63732ede1652f7ad0da29b
Author: Stone <masaike@qq.com>
Date: Thu Apr 22 19:04:57 2021 +0800

Add file1.js

A file1.js

最后一行的A 表示“added”

Viewing the Changes Across Commits

查看两个commit版本的区别:

1
2
3
4
5
6
7
8
9
$ git diff HEAD~2 HEAD
diff --git a/file1.js b/file1.js
index ce01362..24defb6 100644
--- a/file1.js
+++ b/file1.js
@@ -1 +1,2 @@
hello
+A new line of code
\ No newline at end of file

查看区别的简略信息:

1
2
3
4
5
$ git diff HEAD~2 HEAD --name-only
file1.js

$ git diff HEAD~2 HEAD --name-status
M file1.js

上面代码块的最后一行中的“M”表示“modified”。

查看两个commit版本中某个文件的区别:

1
2
3
4
5
6
7
8
9
$ git diff HEAD~2 HEAD file1.js
diff --git a/file1.js b/file1.js
index ce01362..24defb6 100644
--- a/file1.js
+++ b/file1.js
@@ -1 +1,2 @@
hello
+A new line of code
\ No newline at end of file

Checking Out a Commit

LAST表示最近commit,FIRST表示最初commit:

3_03 (7)

MASTER分支指针指向该分支最近的commit:

3_03 (1)

master只是其中的一个分支,事实上一个project可能会有许多分支,所以要用HEAD指向当前working的分支:

3_03 (2)

使用 git checkout 命令之后,HEAD指向指定的commit了:

3_03 (3)

具体例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(master)$ git checkout d6f4cc6
Note: switching to 'd6f4cc6'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

git switch -c <new-branch-name>

Or undo this operation with:

git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at d6f4cc6 Initial commit

HEAD指向d6f4cc6而不是master了,所以是’detached HEAD’ state。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
((d6f4cc6...))$ git log --oneline
d6f4cc6 (HEAD) Initial commit
3fd1e3e Remove unused code
b184de1 Remove unused code
dd03e4e Fix the bug
3b634ca add Lines
a787fca add line
568c0fc Initial commit.

((d6f4cc6...))$ git log --oneline --all
d7d9bfb (master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 (HEAD) Initial commit
3fd1e3e Remove unused code
b184de1 Remove unused code
dd03e4e Fix the bug
3b634ca add Lines
a787fca add line
568c0fc Initial commit.

此时不能有new commit了,因为如果有new commit:

3_03 (5)

当HEAD指回master时:

3_03 (6)

这个new commit再也无法被访问到,就是一个dead commit了。

HEAD指回master:

1
2
3
4
5
((6f4cc6...))$ git checkout master
Previous HEAD position was d6f4cc6 Initial commit
Switched to branch 'master'

(master)$

Finding Bugs Using Bisect

可以用Bisect查找是哪次commit有bug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(master)$ git log --oneline --all
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 add data
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 Initial commit

开始。如果当前commit是bad commit,告诉它:

1
2
3
(master)$ git bisect start

(master|BISECTING)$ git bisect bad

检查发现最开始的commit是good commit,告诉它:

1
2
3
(master|BISECTING)$ git bisect good d6f4cc6
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[fdb7fb6ef27ebfafaa2f7941201c2492c9f9d5ce] add data

说是需要检查5个修改,大概要3个步骤。

可以看到HEAD detach了,指向 good commit 和 bad commit 中间的 commit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
((fdb7fb6...)|BISECTING) $ git log --oneline --all
d7d9bfb (master, refs/bisect/bad) refactor file1 //---------bad--------
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 (HEAD) add data //---------HEAD--------
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 (refs/bisect/good-d6f4cc6574d699b11d91e52aa10543baf65c9af3) Initial commit //---------good--------

当前commit是good commit,告诉它:

1
2
3
((fdb7fb6...)|BISECTING)$ git bisect good
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[78daaab1d24ce993cbd82ab972cfeb9612369ed8] Delete file1.js

说是还需要检查2个修改,大概要2个步骤。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
((78daaab...)|BISECTING)$ git log --oneline --all
d7d9bfb (master, refs/bisect/bad) refactor file1 //---------bad--------
d2acf0e Refactor code
9b82d1b Add file1.js
78daaab (HEAD) Delete file1.js //---------HEAD--------
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 (refs/bisect/good-fdb7fb6ef27ebfafaa2f7941201c2492c9f9d5ce) add data //---------new good--------
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 (refs/bisect/good-d6f4cc6574d699b11d91e52aa10543baf65c9af3) Initial commit //---------old good--------

Once again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
((78daaab...)|BISECTING)$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 1 step)
[d2acf0efae32ea3ffc555fbfc6e432a656dba66c] Refactor code

((d2acf0e...)|BISECTING)$ git log --oneline --all
d7d9bfb (master, refs/bisect/bad) refactor file1 //----------bad--------
d2acf0e (HEAD) Refactor code //---------HEAD--------
9b82d1b Add file1.js
78daaab (refs/bisect/good-78daaab1d24ce993cbd82ab972cfeb9612369ed8) Delete file1.js //---------new good--------
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 (refs/bisect/good-fdb7fb6ef27ebfafaa2f7941201c2492c9f9d5ce) add data
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 (refs/bisect/good-d6f4cc6574d699b11d91e52aa10543baf65c9af3) Initial commit

Once again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
((d2acf0e...)|BISECTING)$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[9b82d1b30e0ea17c2a63732ede1652f7ad0da29b] Add file1.js

((9b82d1b...)|BISECTING)$ git log --oneline --all
d7d9bfb (master) refactor file1
d2acf0e (refs/bisect/bad) Refactor code
9b82d1b (HEAD) Add file1.js
78daaab (refs/bisect/good-78daaab1d24ce993cbd82ab972cfeb9612369ed8) Delete file1.js
133904b commit file1.ls
0f62ff0 remove all js files
fdb7fb6 (refs/bisect/good-fdb7fb6ef27ebfafaa2f7941201c2492c9f9d5ce) add data
62416e2 add files
fde6777 modified
f264740 modified
9ed82f0 Add gitignore
70800e8 Refactor code
d6f4cc6 (refs/bisect/good-d6f4cc6574d699b11d91e52aa10543baf65c9af3) Initial commit

也可以用HEAD:好的,终于找到了:

1
2
3
4
5
6
7
8
9
10
11
((9b82d1b...)|BISECTING)$ git bisect bad
9b82d1b30e0ea17c2a63732ede1652f7ad0da29b is the first bad commit
commit 9b82d1b30e0ea17c2a63732ede1652f7ad0da29b
Author: Stone <masaike@qq.com>
Date: Thu Apr 22 19:04:57 2021 +0800

Add file1.js

file1.js | 1 +
1 file changed, 1 insertion(+)
create mode 100644 file1.js

HEAD指回master:

1
2
3
4
5
((9b82d1b...)|BISECTING)$ git bisect reset
Previous HEAD position was 9b82d1b Add file1.js
Switched to branch 'master'

(master)$

Finding Contributors Using Shortlog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ git shortlog -n
Stone (19):
Initial commit.
add line
add Lines
Fix the bug
Remove unused code
Remove unused code
Initial commit
Refactor code
Add gitignore
modified
modified
add files
add data
remove all js files
commit file1.ls
Delete file1.js
Add file1.js
Refactor code
refactor file1
1
2
3
4
5
6
7
8
9
10
11
$ git shortlog -n -s
19 Stone

$ git shortlog -n -s -e
19 Stone <masaike@qq.com>

$ git shortlog -n -s -e --after="2020-04-21"
19 Stone <masaike@qq.com>

$ git shortlog -n -s -e --before="2021-04-22"
12 Stone <masaike@qq.com>

Viewing the History of a File

查看某文件的修改历史(简略信息):

1
2
3
4
$ git log --oneline file1.js
d7d9bfb (HEAD -> master) refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js

查看文件修改的状态:

1
2
3
4
5
6
7
8
9
10
$ git log --oneline --stat file1.js
d7d9bfb (HEAD -> master) refactor file1
file1.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
d2acf0e Refactor code
file1.js | 1 +
1 file changed, 1 insertion(+)
9b82d1b Add file1.js
file1.js | 1 +
1 file changed, 1 insertion(+)

具体信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ git log --oneline --patch file1.js
d7d9bfb (HEAD -> master) refactor file1
diff --git a/file1.js b/file1.js
index 56f593b..24defb6 100644
--- a/file1.js
+++ b/file1.js
@@ -1,2 +1,2 @@
hello
-A new line of code
+A new line of code
\ No newline at end of file
d2acf0e Refactor code
diff --git a/file1.js b/file1.js
index ce01362..56f593b 100644
--- a/file1.js
+++ b/file1.js
@@ -1 +1,2 @@
hello
+A new line of code
9b82d1b Add file1.js
diff --git a/file1.js b/file1.js
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/file1.js
@@ -0,0 +1 @@
+hello

Restoring a Deleted File

不小心删除了文件file1.js:

1
2
3
4
5
6
7
$ git rm file1.js
rm 'file1.js'

$ git commit -m "Remove file1.js"
[master e2ebefd] Remove file1.js
1 file changed, 2 deletions(-)
delete mode 100644 file1.js

想恢复它,就从d7d9bfb的commit恢复到本地目录,然后重新commit到仓库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ git log --oneline -- file1.js
e2ebefd (HEAD -> master) Remove file1.js
d7d9bfb refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js

$ git checkout d7d9bfb file1.js
Updated 1 path from 8623496

$ git status -s
A file1.js

$ git commit -m "Restore file1.js"
[master 9328b9b] Restore file1.js
1 file changed, 2 insertions(+)
create mode 100644 file1.js

Blaming

Find the author of a perticular line (看看是谁写的烂代码):

1
2
3
4
5
$ git blame file1.js
9328b9b8 (Stone 2021-04-23 15:10:50 +0800 1) hello
49019215 (Stone 2021-04-23 15:19:09 +0800 2) A new line of code
49019215 (Stone 2021-04-23 15:19:09 +0800 3) Sky
49019215 (Stone 2021-04-23 15:19:09 +0800 4) Moon

加上-e看邮件:

1
2
3
4
5
$ git blame -e file1.js
9328b9b8 (<masaike@qq.com> 2021-04-23 15:10:50 +0800 1) hello
49019215 (<masaike@qq.com> 2021-04-23 15:19:09 +0800 2) A new line of code
49019215 (<masaike@qq.com> 2021-04-23 15:19:09 +0800 3) Sky
49019215 (<masaike@qq.com> 2021-04-23 15:19:09 +0800 4) Moon

加上-L看某几行:

1
2
3
$ git blame -e -L 1,2 file1.js
9328b9b8 (<masaike@qq.com> 2021-04-23 15:10:50 +0800 1) hello
49019215 (<masaike@qq.com> 2021-04-23 15:19:09 +0800 2) A new line of code

Tagging

给某次commit加个tag(实际上是个指向该commit的指针):

1
$ git tag v1.0 9328b9b
1
2
3
4
5
6
7
$ git log --oneline
4901921 (HEAD -> master) add 2 lines in file1.js
9328b9b (tag: v1.0) Restore file1.js //----------------------------
e2ebefd Remove file1.js
d7d9bfb refactor file1
d2acf0e Refactor code
9b82d1b Add file1.js

然后就可以用这个tag表示这个commit了,如:

1
$ git checkout v1.0

给当前commit(即MASTER指向的)起个详细的tag:

1
$ git tag -a v1.1 -m "My version 1.1"

查看目前的所有tags:

1
2
3
4
5
6
7
$ git tag
v1.0
v1.1

$ git tag -n
v1.0 Restore file1.js //-----和commit信息一样-----
v1.1 My version 1.1 //------tag信息------------

在此例中,v1.0是个lightweight tag,v1.1是个annotated tag。

annotated tag可以显示更详细的信息:加tag者的信息和commit的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ git show v1.1
tag v1.1
Tagger: Stone <masaike@qq.com>
Date: Fri Apr 23 15:27:43 2021 +0800

My version 1.1

commit 490192157cd80c704f4f85e2b2883685e3423f91 (HEAD -> master, tag: v1.1)
Author: Stone <masaike@qq.com>
Date: Fri Apr 23 15:19:09 2021 +0800

add 2 lines in file1.js

diff --git a/file1.js b/file1.js
index 24defb6..e27584b 100644
--- a/file1.js
+++ b/file1.js
@@ -1,2 +1,4 @@
hello
-A new line of code
\ No newline at end of file
+A new line of code
+Sky
+Moon
\ No newline at end of file

删除tag:

1
2
$ git tag -d v1.1
Deleted tag 'v1.1' (was c847e27)