除了定製輸出格式的選項之外,git log
還有許多非常實用的限制輸出長度的選項,也就是只輸出部分提交資訊。之前我們已經看到過-2
了,它只顯示最近的兩條提交,實際上,這是-
選項的寫法,其中的n
可以是任何自然數,表示僅顯示最近的若干條提交。不過實踐中我們是不太用這個選項的,git 在輸出所有提交時會自動呼叫分頁程式(less),要看更早的更新只需翻到下頁即可。
另外還有按照時間作限制的選項,比如--since
和--until
。下面的命令列出所有最近兩周內的提交:
$ git log --since=2.weeks
你可以給出各種時間格式,比如說具體的某一天(「2008-01-15」),或者是多久以前(「2 years 1 day 3 minutes ago」)。
還可以給出若干搜尋條件,列出符合的提交。用--author
選項顯示指定作者的提交,用--grep
選項搜尋提交說明中的關鍵字。(請注意,如果要得到同時滿足這兩個選項搜尋條件的提交,就必須用--all-match
選項。)
如果只關心某些檔案或者目錄的歷史提交,可以在git log
選項的最後指定它們的路徑。因為是放在最後位置上的選項,所以用兩個短劃線(--
)隔開之前的選項和後面限定的路徑名。
表 2-3 還列出了其他常用的類似選項。
選項 說明
-(n) 僅顯示最近的 n 條提交
--since, --after 僅顯示指定時間之後的提交。
--until, --before 僅顯示指定時間之前的提交。
--author 僅顯示指定作者相關的提交。
--committer 僅顯示指定提交者相關的提交。
來看乙個實際的例子,如果要檢視 git 倉庫中,2008 年 10 月期間,junio hamano 提交的但未合併的測試指令碼(位於專案的 t/ 目錄下的檔案),可以用下面的查詢命令:
$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
5610e3b - fix testcase failure when extended attribute
f563754 - demonstrate breakage of detached checkout wi
d1a43f2 - reset --hard/read-tree --reset -u: remove un
51a94af - fix "checkout --track -b newbranch" on detac
b0ad11e - pull: allow "git pull origin $something:$cur
git 專案有 20,000 多條提交,但我們給出搜尋選項後,僅列出了其中滿足條件的 6 條。
有時候圖形化工具更容易展示歷史提交的變化,隨 git 一同發布的 gitk 就是這樣一種工具。它是用 tcl/tk 寫成的,基本上相當於git log
命令的視覺化版本,凡是git log
可以用的選項也都能用在 gitk 上。在專案工作目錄中輸入 gitk 命令後,就會啟** 2-2 所示的介面。
圖 2-2. gitk 的圖形介面
上半個視窗顯示的是歷次提交的分支祖先圖譜,下半個視窗顯示當前點選的提交對應的具體差異。
任何時候,你都有可能需要撤消剛才所做的某些操作。接下來,我們會介紹一些基本的撤消操作相關的命令。請注意,有些操作並不總是可以撤消的,所以請務必謹慎小心,一旦失誤,就有可能丟失部分工作成果。
有時候我們提交完了才發現漏掉了幾個檔案沒有加,或者提交資訊寫錯了。想要撤消剛才的提交操作,可以使用--amend
選項重新提交:
$ git commit --amend
此命令將使用當前的暫存區域快照提交。如果剛才提交完沒有作任何改動,直接執行此命令的話,相當於有機會重新編輯提交說明,但將要提交的檔案快照和之前的一樣。
啟動文字編輯器後,會看到上次提交時的說明,編輯它確認沒問題後儲存退出,就會使用新的提交說明覆蓋剛才失誤的提交。
如果剛才提交時忘了暫存某些修改,可以先補上暫存操作,然後再執行--amend
提交:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
上面的三條命令最終只是產生乙個提交,第二個提交命令修正了第乙個的提交內容。
接下來的兩個小節將演示如何取消暫存區域中的檔案,以及如何取消工作目錄中已修改的檔案。不用擔心,檢視檔案狀態的時候就提示了該如何撤消,所以不需要死記硬背。來看下面的例子,有兩個修改過的檔案,我們想要分開提交,但不小心用git add .
全加到了暫存區域。該如何撤消暫存其中的乙個檔案呢?其實,git status
的命令輸出已經告訴了我們該怎麼做:
$ git add .
$ git status
# on branch master
# changes to be committed:
# (use "git reset head
..." to unstage)
## modified: readme.txt
# modified: benchmarks.rb
#
就在 「changes to be committed」 下面,括號中有提示,可以使用git reset head ...
的方式取消暫存。好吧,我們來試試取消暫存 benchmarks.rb 檔案:
$ git reset head benchmarks.rb
benchmarks.rb: locally modified
$ git status
# on branch master
# changes to be committed:
# (use "git reset head
..." to unstage)
## modified: readme.txt
## changed but not updated:
# (use "git add
..." to update what will be committed)
# (use "git checkout --
..." to discard changes in working directory)
## modified: benchmarks.rb
#
這條命令看起來有些古怪,先別管,能用就行。現在 benchmarks.rb 檔案又回到了之前已修改未暫存的狀態。
如果覺得剛才對 benchmarks.rb 的修改完全沒有必要,該如何取消修改,回到之前的狀態(也就是修改之前的版本)呢?git status
同樣提示了具體的撤消方法,接著上面的例子,現在未暫存區域看起來像這樣:
# changed but not updated:
# (use "git add
..." to update what will be committed)
# (use "git checkout --
..." to discard changes in working directory)
## modified: benchmarks.rb
#
在第二個括號中,我們看到了拋棄檔案修改的命令(至少在 git 1.6.1 以及更高版本中會這樣提示,如果你還在用老版本,我們強烈建議你公升級,以獲取最佳的使用者體驗),讓我們試試看:
$ git checkout -- benchmarks.rb
$ git status
# on branch master
# changes to be committed:
# (use "git reset head
..." to unstage)
## modified: readme.txt
#
可以看到,該檔案已經恢復到修改前的版本。你可能已經意識到了,這條命令有些危險,所有對檔案的修改都沒有了,因為我們剛剛把之前版本的檔案複製過 來重寫了此檔案。所以在用這條命令前,請務必確定真的不再需要保留剛才的修改。如果只是想回退版本,同時保留剛才的修改以便將來繼續工作,可以用下章介紹 的 stashing 和分支來處理,應該會更好些。
記住,任何已經提交到 git 的都可以被恢復。即便在已經刪除的分支中的提交,或者用--amend
重新改寫的提交,都可以被恢復(關於資料恢復的內容見第九章)。所以,你可能失去的資料,僅限於沒有提交過的,對 git 來說它們就像從未存在過一樣。
Git學習筆記之二《基礎》
取得專案的git倉庫 兩種方法 在視訊記憶體的目錄下,通過匯入所有檔案裡來建立新的git倉庫 從已有的git倉庫轉殖出乙個新的映象倉庫 從當前目錄初始化 git init 如果當前目錄下有幾個檔案想要納入版本控制,先用git add命令新增,然後提交 git add c git add readme...
Git 學習(二)Git 基礎
git 在儲存和對待各種資訊的時候與其它版本控制系統如 svn 等等有很大差異,儘管操作起來的命令形式非常相近,理解這些差異將有助於防止你使用中的困惑。如果有使用 svn 等其他版本控制系統的經驗,應該知道它們的工作原理是記錄每一次的變動。將它們儲存的資訊看作是一組基本檔案和每個檔案隨時間逐步累積的...
學習Git命令之二
使用git clone 命令將遠端倉庫的 拷貝到本地倉庫中。遠端分支的名字格式是 大多數的開發者會將remote name 命名為origin。與對本地倉庫的操作不同,當對遠端分支進行操作是,master分支並不會自動更新。切換到遠端分支時,你將被置於head,而不是這些分支上 即head hash...