基本款
之前我們已經做了幾次 commit 的提交,那我們應該怎麼查看這些紀錄呢?指令是 git log
$ git log
commit 462682ddf12ddebd3e7b4c6796ffb0907560f08b (HEAD -> master)
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 16 13:34:36 2020 +0800
沒東西
commit 0fdb52fe4c91c1f2b342922ea031ab63c6d1078f
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 16 13:01:25 2020 +0800
加入git並新增welcome.txt檔案
我後來有把 user.name 跟 user.email 改過,所以這邊的紀錄不是 nvda
從上面的資訊可以看出我們目前有兩個提交:
- 越新的資訊會在越上面
- 是誰在什麼時候 commit 的
- commit 的內容是什麼
至於在每個 commit 後面的那串像亂碼的字串是什麼?462682ddf12ddebd3e7b4c6796ffb0907560f08b
那是使用 sha1 演算法產生出來的每個提交代號,它的重複率非常非常低,所以我們可以把它當作是每個版本的代號。
在 git 當中就是認這個代號,像是我們要切換到不同的 commit 狀態就要靠這些代號,這也就是所謂的版本號了。
而在最上面的 commit 後面有個 (HEAD -> master)
是告訴我們目前正處在這個 commit 版本狀態中。
master
是預設的主分支,這部分我們之後再說。
另外,git log 可以有一些參數,例如 --oneline
$ git log --oneline
462682d (HEAD -> master) 沒東西
0fdb52f 加入git並新增welcome.txt檔案
這樣每個 commit 就只有一行,如果我們想快速的瀏覽很多 commit 的時候就很方便,
像是我們只有自己 commit 所以可以略掉那些作者資訊,最主要有版本號、commit內容跟位在何處就足夠了。
這邊的版本號也縮短了,對 git 來說只要前面的 6 到 8 碼其實就夠了。
那如果前幾碼有重複的話也沒關係,git 會告訴我們無法辨識,此時就再多打幾碼就好。
還有一個 --graph
的參數:
$ git log --oneline --graph
* 462682d (HEAD -> master) 沒東西
* 0fdb52f 加入git並新增welcome.txt檔案
跟剛剛的 --oneline
比起來只有一個不同,就是最前面多了 *` 星號。
其實在圖形介面中可以看到,藍色圈圈與空心圈圈,空心圈圈就是 HEAD 所在版本,沒關係,我們看字也看得出來。
進階版
如捰有很多 log 的狀況,需要使用某些條件來查尋 log 而不是逐條逐條的看,應該怎麼做?
# 查詢提交者是 logo 的紀錄
$ git log --oneline --author='logo'
462682d (HEAD -> master) 沒東西
0fdb52f 加入git並新增welcome.txt檔案
那因為目前都是 logo 提交的,所以看起來都一樣。
在引號中使用 |
或符號,就可以查到多個提交者的 commit
因為是在引號中,所以在或符號前面要再加上一個反斜線 \
來跳脫才有效,
不然 git 會以為 |
這個符號也是作者名字的一部份。
想找 commit 內容有提到 東西
這兩個字的紀錄:
$ git log --oneline --grep='東西'
462682d (HEAD -> master) 沒東西
想找跟 welcome.txt
這個檔案變動有關的紀錄
$ git log --oneline -- welcome.txt
0fdb52f 加入git並新增welcome.txt檔案
實際上 commit 沒提到這個檔案也無所謂,因為他找的不是 commit 內容而是實際更動的動作。
多檔案就使用空格隔開檔名即可。
而要不要加 --oneline
只是 log 顯示的方式,並不影響搜尋結果。
也可以用時間段來查找相關紀錄,例如查尋今天早上九點到中午十二點的所有紀錄
$ git log --oneline --since="9am" --until="12am"
目前沒有,所以沒有找到。
$ git log --oneline --since="9am" --until="17fm" --after='2020-02-01'
462682d (HEAD -> master) 沒東西
0fdb52f 加入git並新增welcome.txt檔案
上面是查找從 2020 年 2 月 1 號以後每天早上 9 點到下午 5 點的所有紀錄。
$ git log --oneline -S '你'
0fdb52f 加入git並新增welcome.txt檔案
上面的搜尋條件是提交的檔案內容有 你
這個字的紀錄,
因為我們在該筆紀錄中,welcome.txt
裡有寫入 你好
這兩個字。
其實還有很多參數用法,可以使用 git log --help
來查尋。
與該檔案相關的紀錄
之前我們介紹過 git log 指令來查看我們提交的 log 紀錄。
但我們如果是想觀察跟某個檔案有關的所有 log 提交紀錄時該怎麼辦?
那就加上該檔案的檔名作為參數,即可列出與該檔案相關的紀錄。
$ git log hello.txt
commit d321f73c6d05ab8b96c5c7f4abb75099d55b823e
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 23 22:30:28 2020 +0800
將 welcome.txt 更名為 hello.txt 並加入 test.py 檔案
當然還是可以搭配之前提的 --oneline
等參數使用。
該提交的實際行為
可是光看到這些紀錄的提交訊息,有時還是無法確定當時到底對他做了什麼事情,
像有時候程式中加了某個功能,在提交紀錄時可以看到說明,但實際到底加了什麼內容還是不清楚,
可以加上 -p
參數,先來加一筆修改紀錄:
# 在 hello.txt 檔案最後加一行字,該行內容為測試兩個字
$ echo '測試' >> hello.txt
# 列出檔案內容
$ cat hello.txt
你好
我很好
測試
# 存到暫存區並提交
$ git add .
$ git commit -m '在 hello.txt 最後加了一行字'
[master b7df611] 在 hello.txt 最後加了一行字
1 file changed, 1 insertion(+)
接著看一下詳細 log
$ git log -p hello.txt
commit b7df611332a5a7f44b667c24e40da1bcc92c00c5
Author: Logo Kuo <logo@forblind.org.tw>
Date: Fri Feb 28 21:31:22 2020 +0800
在 hello.txt 最後加了一行字
diff --git a/hello.txt b/hello.txt
index 65c6e5c..68032d3 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
你好
我很好
+測試
commit d321f73c6d05ab8b96c5c7f4abb75099d55b823e
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 23 22:30:28 2020 +0800
將 welcome.txt 更名為 hello.txt 並加入 test.py 檔案
diff --git a/hello.txt b/hello.txt
new file mode 100644
index 0000000..65c6e5c
--- /dev/null
+++ b/hello.txt
@@ -0,0 +1,2 @@
+你好
+我很好
雖然格式與內容看起來有點複雜,但大致還是可以看出:
- 第一筆紀錄的檔案內容 測試 前面有個加號,就表示是該次新增的內容,減號就是刪除的內容
- 第二筆紀錄是改名,所以有
new file
的標示,內容那兩行就都算是新增出來的,應該還記得更名就是刪除再新增吧
完整內容
上面的紀錄看起來是該提交所做的事情,但我們如果是想看某個檔案的全部內容狀況呢?
例如你發現 hello.txt 的第三行是有問題的,想知道是誰在什麼時候加了這一行,就可以列出檔案完整資訊來觀察,
指令是 blame
後面加檔名:
$ git blame hello.txt
^0fdb52f welcome.txt (Logo Kuo 2020-02-16 13:01:25 +0800 1) 你好
^0fdb52f welcome.txt (Logo Kuo 2020-02-16 13:01:25 +0800 2) 我很好
b7df6113 hello.txt (Logo Kuo 2020-02-28 21:31:22 +0800 3) 測試
以上的資訊非常清楚,包括 hello.txt 還沒被改名時的紀錄都有,
資訊大致上包括:
- 提交的版本號
- 檔名
- 提交者
- 時間
- 檔案內的行號
- 該行的內容
如果檔案很大,只想看某個區間的紀錄,可以使用 -L
參數並指定行號,注意是大寫字母。
$ git blame -L 2,7 test.py
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 2) '''這是一個銀行類別,裡
面有存款金額與存錢、提錢等功能'''
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 3)
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 4) class Riches:
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 5) ''' 這是一個財富類別
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 6) 裡面有兩個屬性,分別是 m
oney 現金與 mybank 銀行存款
d321f73c (Logo Kuo 2020-02-23 22:30:28 +0800 7) '''
以上顯示的是該檔案 test.py 第 2 到 7 行的紀錄。
有時一個專案很久沒碰了,想要繼續更新或新增功能時,可以利用上面這些指令幫你回憶一下上次做了什麼。
當然系統被改壞了用來抓兇手也是很普遍的用法。
所以在使用 log 時可以針對某些條件來調出紀錄,也可以針對某個檔案讀取紀錄,
對於該 log 做了什麼事也能看到,這樣讓我們可以更靈活的利用 git 管理檔案。
補充
以上這些輸出的資訊會比較多,在超過一頁資訊時 git bash 的提示符號會變成 :
此時表示進入了瀏覽狀態,常用指令如下:
- 空白鍵:下一頁
- p 上一頁
- q 離開瀏覽狀態回到
$
而看到提示符號 (END)
就表示看完囉。
如果覺得這樣瀏覽還是不方便,或者有編輯的需求,那就在原本的指令後面加上 > 檔名
把資訊導入某個檔案再使用瀏覽器開啟該檔案進行瀏覽或編輯。
$ git blame test.py > look.txt
還記得之前使用 echo 來把內容加到檔案中吧,就是利用這個原理。
再次提醒,一個大於會把後面的檔案內容清空,然後再新增資訊進去,而兩個大於是把資訊添加在該檔案後面,
而這兩種方式當沒有指定的檔案時都會自行建立一個並添加內容。
刪檔與更名
不管是刪除檔案或更改檔名,對 git 來說就是一種更改紀錄而已。
刪檔
平常我們在工作目錄下運作,通常是使用檔案管理之類的程式來處理檔案。
例如按 delete 或利用快顯功能表的刪除都可以,甚至是 shift+delete 的強制刪除也行。
但我這邊選擇用指令在 git bash 下刪檔,目的是讓大家可以知道我做了什麼事,不然平常是不需要特別開 git bash 刪檔的。
$ rm welcome.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: welcome.txt
no changes added to commit (use "git add" and/or "git commit -a")
從上面的資訊我們至少看出兩點:
- welcome.txt 上面有 deleted 標誌,表示他被刪了
- Changes not staged for commit 表示現在的 git 狀態是做了變更但還沒 add 到暫存區,當然也就還沒 commit 了
那就把他加到暫存區吧
$ git add .
# 接著觀察一下狀態
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: welcome.txt
從上面的資訊我們至少看出兩點:
- welcome.txt 上面有 deleted 標誌,表示他被刪了
- Changes to be committed 表示目前 git 的狀態是已經加到暫存區但還沒 commit 推進倉庫
如果使用 git rm welcome.txt
就是把刪除跟 add 的兩個動作合成一個指令,
實務上很少用,因為我們比較不會在 git bash 下刪檔。
如果使用 --cached
也就是刪除時加上這個參數,
其實不是刪檔,而是移除這個檔案的 git 追蹤,意思就是 git 以後不會再控管他了。
移除追蹤後得到的狀態長這樣:
$ git rm welcome.txt --cached
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: welcome.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
welcome.txt
那個 Untracked files
就表示這個檔案已經停止追蹤了。
以上這個 --cached
參數操作我們假設是在其他地方做的不影響原本的工作目錄。
那我們把剛剛刪好檔案的部分 commit 提交上去吧
$ git commit -m '刪除 welcome.txt'
[master c708443] 刪除 welcome.txt
1 file changed, 2 deletions(-)
delete mode 100644 welcome.txt
# 看一下 log
$ git log -1
commit c708443e21e8fba120ad1437ebc17a3562315559 (HEAD -> master)
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 23 21:51:47 2020 +0800
刪除 welcome.txt
參數 -1
就是只列出最新的一筆 log 資訊。
在這裡讓我們先回到過去還沒刪除 welcome.txt 的美好時光吧,因為我們還沒練習改名。
回春指令之後再解釋,因為我們先把重點放在刪檔與更名上。
$ git reset --hard HEAD~
HEAD is now at 462682d 沒東西
$ git log -1
commit 462682ddf12ddebd3e7b4c6796ffb0907560f08b (HEAD -> master)
Author: Logo Kuo <logo@forblind.org.tw>
Date: Sun Feb 16 13:34:36 2020 +0800
沒東西
$ ls
welcome.txt
真神奇,剛剛的刪除 commit 紀錄不見了,檔案也回來了。目前先理解成紀錄消失就表示沒做過該紀錄的所有動作。
更名
跟上面刪檔一樣,可以用檔案總管的快顯功能表或快速鍵 F2 來變更檔名,
那我們還是先用指令來更名讓大家看得到動作:
$ mv welcome.txt hello.txt
# 當然還是要看一下狀態
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: welcome.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.txt
no changes added to commit (use "git add" and/or "git commit -a")
雖然是更名,但對 git 來說其實是兩個動作,也就是刪除 welcome.txt 並新增 hello.txt
而且新的檔案狀態是還沒被追蹤。
$ git add .
# 剛開始使用 git 最好做每個動作都仔細觀察狀態,這樣我們才知道 git 到底做了什麼
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: welcome.txt -> hello.txt
git 很聰明吧,知道這只是 renamed
更名動作而已。
當然 git mv welcome.txt hello.txt
也可以合併兩段式指令為一個指令了。
記得要 commit 提交才算是完成整個操作流程喔。
不想改名的話就再改回來再提交囉。
最後更新:2020-04-17 09:51:48
From: 211.23.21.202
By: 阿慶