## git log 顯示一個分支中提交的更改記錄
到目前為止,我們已經提交快照到項目中,在不同的各自分離的上下文中切換, 但假如我們忘了自己是如何到目前這一步的那該怎么辦?或者假如我們想知道此分支與彼分支到底有啥區別? Git 提供了一個告訴你使你達成當前快照的所有提交消息的工具,叫做?`git log`。
要理解日志(log)命令,你需要了解當執行?`git commit`?以存儲一個快照的時候,都有啥信息被保存了。 除了文件詳單、提交消息和提交者的信息,Git 還保存了你的此次提交所基于的快照。 也就是,假如你克隆了一個項目,你是在什么快照的基礎上做的修改而得到新保存的快照的? 這有益于為項目進程提供上下文,使 Git 能夠弄明白誰做了什么改動。 如果 Git 有你的快照所基于的快照的話,它就能自動判斷你都改變了什么。而新提交所基于的提交,被稱作新提交的“父親”。
某分支的按時間排序的“父親”列表,當你在該分支時,可以執行?`git log`?以查看。 例如,如果我們在本章中操作的 Hello World 項目中執行?`git log`,我們可以看到已提交的消息。
~~~
$ git log
commit 8d585ea6faf99facd39b55d6f6a3b3f481ad0d3d
Merge: 3cbb6aa 3ac015d
Author: Scott Chacon
Date: Fri Jun 4 12:59:47 2010 +0200
Merge branch 'fix_readme'
Conflicts:
README
commit 3cbb6aae5c0cbd711c098e113ae436801371c95e
Author: Scott Chacon
Date: Fri Jun 4 12:58:53 2010 +0200
fixed readme title differently
commit 3ac015da8ade34d4c7ebeffa2053fcac33fb495b
Author: Scott Chacon
Date: Fri Jun 4 12:58:36 2010 +0200
fixed readme title
commit 558151a95567ba4181bab5746bc8f34bd87143d6
Merge: b7ae93b 3467b0a
Author: Scott Chacon
Date: Fri Jun 4 12:37:05 2010 +0200
Merge branch 'change_class'
...
~~~
我們可以用?`--oneline`?選項來查看歷史記錄的緊湊簡潔的版本。
~~~
$ git log --oneline
8d585ea Merge branch 'fix_readme'
3cbb6aa fixed readme title differently
3ac015d fixed readme title
558151a Merge branch 'change_class'
b7ae93b added from ruby
3467b0a changed the class name
17f4acf first commit
~~~
這告訴我們的是,此項目的開發歷史。如果提交消息描述性很好,這就能為我們提供關于有啥改動被應用、或者影響了當前快照的狀態、以及這快照里頭都有啥。
我們還可以用它的十分有幫助的?`--graph`?選項,查看歷史中什么時候出現了分支、合并。以下為相同的命令,開啟了拓撲圖選項:
~~~
$ git log --oneline --graph
* 8d585ea Merge branch 'fix_readme'
|\
| * 3ac015d fixed readme title
* | 3cbb6aa fixed readme title differently
|/
* 558151a Merge branch 'change_class'
|\
| * 3467b0a changed the class name
* | b7ae93b added from ruby
|/
* 17f4acf first commit
~~~
現在我們可以更清楚明了地看到何時工作分叉、又何時歸并。 這對查看發生了什么、應用了什么改變很有幫助,并且極大地幫助你管理你的分支。 讓我們創建一個分支,在里頭做些事情,然后切回到主分支,也做點事情,然后看看?`log`?命令是如何幫助我們理清這倆分支上都發生了啥的。
首先我們創建一個分支,來添加 Erlang 編程語言的 Hello World 示例 —— 我們想要在一個分支里頭做這個,以避免讓可能還不能工作的代碼弄亂我們的穩定分支。 這樣就可以切來切去,片葉不沾身。
~~~
$ git checkout -b erlang
Switched to a new branch 'erlang'
$ vim erlang_hw.erl
$ git add erlang_hw.erl
$ git commit -m 'added erlang'
[erlang ab5ab4c] added erlang
1 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 erlang_hw.erl
~~~
由于我們玩函數式編程很開心,以至于沉迷其中,又在“erlang”分支中添加了一個 Haskell 的示例程序。
~~~
$ vim haskell.hs
$ git add haskell.hs
$ git commit -m 'added haskell'
[erlang 1834130] added haskell
1 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 haskell.hs
~~~
最后,我們決定還是把 Ruby 程序的類名改回原先的樣子。與其創建另一個分支,我們可以返回主分支,改變它,然后直接提交。
~~~
$ git checkout master
Switched to branch 'master'
$ ls
README ruby.rb
$ vim ruby.rb
$ git commit -am 'reverted to old class name'
[master 594f90b] reverted to old class name
1 files changed, 2 insertions(+), 2 deletions(-)
~~~
現在假設我們有段時間不做這個項目了,我們做別的去了。 當我們回來的時候,我們想知道“erlang”分支都是啥,而主分支的進度又是怎樣。 僅僅看分支的名字,我們是無從知道自己還在里面有 Haskell 的改動的,但是用?`git log`?我們就可以。 如果你在命令行中提供一個分支名字,它就會顯示該分支歷史中“可及”的提交,即從該分支創立起可追溯的影響了最終的快照的提交。
~~~
$ git log --oneline erlang
1834130 added haskell
ab5ab4c added erlang
8d585ea Merge branch 'fix_readme'
3cbb6aa fixed readme title differently
3ac015d fixed readme title
558151a Merge branch 'change_class'
b7ae93b added from ruby
3467b0a changed the class name
17f4acf first commit
~~~
如此,我們很容易就看到分支里頭還包括了 Haskell 代碼(高亮顯示了)。 更酷的是,我們很容易地告訴 Git,我們只對某個分支中可及的提交感興趣。換句話說,某分支中與其他分支相比唯一的提交。
在此例中,如果我們想要合并“erlang”分支,我們需要看當合并的時候,都有啥提交會作用到我們的快照上去。 我們告訴 Git 的方式是,在不想要看到的分支前放一個?`^`。 例如,如果我們想要看“erlang”分支中但不在主分支中的提交,我們可以用?`erlang ^master`,或者反之。
~~~
$ git log --oneline erlang ^master
1834130 added haskell
ab5ab4c added erlang
$ git log --oneline master ^erlang
594f90b reverted to old class name
~~~
這為我們提供了一個良好的、簡易的分支管理工具。它使我們能夠非常容易地查看對某個分支唯一的提交,從而知道我們缺少什么,以及當我們要合并時,會有什么被合并進去。
> **簡而言之**?使用?`git log`?列出促成當前分支目前的快照的提交歷史記錄。這使你能夠看到項目是如何到達現在的狀況的。