如第一章所言,用git config配置 Git,要做的第一件事就是設置名字和郵箱地址:
~~~
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
~~~
從現在開始,你會了解到一些類似以上但更為有趣的設置選項來自定義 Git。
先過一遍第一章中提到的 Git 配置細節。Git 使用一系列的配置文件來存儲你定義的偏好,它首先會查找/etc/gitconfig文件,該文件含有 對系統上所有用戶及他們所擁有的倉庫都生效的配置值(譯注:gitconfig是全局配置文件), 如果傳遞--system選項給git config命令, Git 會讀寫這個文件。
接下來 Git 會查找每個用戶的~/.gitconfig文件,你能傳遞--global選項讓 Git讀寫該文件。
最后 Git 會查找由用戶定義的各個庫中 Git 目錄下的配置文件(.git/config),該文件中的值只對屬主庫有效。 以上闡述的三層配置從一般到特殊層層推進,如果定義的值有沖突,以后面層中定義的為準,例如:在.git/config和/etc/gitconfig的較量中, .git/config取得了勝利。雖然你也可以直接手動編輯這些配置文件,但是運行git config命令將會來得簡單些。
## 客戶端基本配置
Git 能夠識別的配置項被分為了兩大類:客戶端和服務器端,其中大部分基于你個人工作偏好,屬于客戶端配置。盡管有數不盡的選項,但我只闡述 其中經常使用或者會對你的工作流產生巨大影響的選項,如果你想觀察你當前的 Git 能識別的選項列表,請運行
`$ git config --help`
`git config`的手冊頁(譯注:以man命令的顯示方式)非常細致地羅列了所有可用的配置項。
### core.editor
Git默認會調用你的環境變量editor定義的值作為文本編輯器,如果沒有定義的話,會調用Vi來創建和編輯提交以及標簽信息, 你可以使用core.editor改變默認編輯器:
`$ git config --global core.editor emacs`
現在無論你的環境變量editor被定義成什么,Git 都會調用Emacs編輯信息。
### commit.template
如果把此項指定為你系統上的一個文件,當你提交的時候, Git 會默認使用該文件定義的內容。 例如:你創建了一個模板文件`$HOME/.gitmessage.txt`,它看起來像這樣:
~~~
subject line
what happened
[ticket: X]
~~~
設置`commit.template,`當運行`git commit`時, Git 會在你的編輯器中顯示以上的內容, 設置`commit.template`如下:
~~~
$ git config --global commit.template $HOME/.gitmessage.txt
$ git commit
~~~
然后當你提交時,在編輯器中顯示的提交信息如下:
~~~
subject line
what happened
[ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C
~~~
如果你有特定的策略要運用在提交信息上,在系統上創建一個模板文件,設置 Git 默認使用它,這樣當提交時,你的策略每次都會被運用。
### core.pager
`core.pager`指定 Git 運行諸如log、diff等所使用的分頁器,你能設置成用more或者任何你喜歡的分頁器(默認用的是less), 當然你也可以什么都不用,設置空字符串:
`$ git config --global core.pager ''`
這樣不管命令的輸出量多少,都會在一頁顯示所有內容。
### user.signingkey
如果你要創建經簽署的含附注的標簽(正如第二章所述),那么把你的GPG簽署密鑰設置為配置項會更好,設置密鑰ID如下:
`$ git config --global user.signingkey <gpg-key-id>`
現在你能夠簽署標簽,從而不必每次運行git tag命令時定義密鑰:
`$ git tag -s <tag-name>`
### core.excludesfile
正如第二章所述,你能在項目庫的.gitignore文件里頭用模式來定義那些無需納入 Git 管理的文件,這樣它們不會出現在未跟蹤列表, 也不會在你運行git add后被暫存。然而,如果你想用項目庫之外的文件來定義那些需被忽略的文件的話,用core.excludesfile 通知 Git 該文件所處的位置,文件內容和.gitignore類似。
### help.autocorrect
該配置項只在 Git 1.6.1及以上版本有效,假如你在Git 1.6中錯打了一條命令,會顯示:
~~~
$ git com
git: 'com' is not a git-command. See 'git --help'.
Did you mean this?
commit
~~~
如果你把help.autocorrect設置成1(譯注:啟動自動修正),那么在只有一個命令被模糊匹配到的情況下,Git 會自動運行該命令。
## Git中的著色
Git能夠為輸出到你終端的內容著色,以便你可以憑直觀進行快速、簡單地分析,有許多選項能供你使用以符合你的偏好。
### color.ui
Git會按照你需要自動為大部分的輸出加上顏色,你能明確地規定哪些需要著色以及怎樣著色,設置color.ui為true來打開所有的默認終端著色。
``$ git config --global color.ui true``
設置好以后,當輸出到終端時,Git 會為之加上顏色。其他的參數還有false和`always,false`意味著不為輸出著色,而always則表明在任何情況下都要著色,即使 Git 命令被重定向到文件或管道。Git 1.5.5版本引進了此項配置,如果你擁有的版本更老,你必須對顏色有關選項各自進行詳細地設置。
你會很少用到`color.ui = always,`在大多數情況下,如果你想在被重定向的輸出中插入顏色碼,你能傳遞`--color`標志給 `Git `命令來迫使它這么做,color.ui = true應該是你的首選。
### color.*
想要具體到哪些命令輸出需要被著色以及怎樣著色或者 Git 的版本很老,你就要用到和具體命令有關的顏色配置選項,它們都被置為true、false或always:
~~~
color.branch
color.diff
color.interactive
color.status
~~~
除此之外,以上每個選項都有子選項,可以被用來覆蓋其父設置,以達到為輸出的各個部分著色的目的。例如,讓diff輸出的改變信息以粗體、藍色前景和黑色背景的形式顯示:
`$ git config --global color.diff.meta "blue black bold"`
你能設置的顏色值如:`normal、black、red、green、yellow、blue、magenta、cyan、white,`正如以上例子設置的粗體屬性,想要設置字體屬性的話,可以選擇如:`bold、dim、ul、blink、reverse。`
如果你想配置子選項的話,可以參考git config幫助頁。
## 外部的合并與比較工具
雖然 Git 自己實現了diff,而且到目前為止你一直在使用它,但你能夠用一個外部的工具替代它,除此以外,你還能用一個圖形化的工具來合并和解決沖突從而不必自己手動解決。有一個不錯且免費的工具可以被用來做比較和合并工作,它就是P4Merge(譯注:Perforce圖形化合并工具),我會展示它的安裝過程。
P4Merge可以在所有主流平臺上運行,現在開始大膽嘗試吧。對于向你展示的例子,在Mac和Linux系統上,我會使用路徑名,在Windows上,/usr/local/bin應該被改為你環境中的可執行路徑。
下載P4Merge:
`http://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools`
首先把你要運行的命令放入外部包裝腳本中,我會使用Mac系統上的路徑來指定該腳本的位置,在其他系統上,它應該被放置在二進制文件p4merge所在的目錄中。創建一個merge包裝腳本,名字叫作extMerge,讓它帶參數調用p4merge二進制文件:
~~~
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*
~~~
diff包裝腳本首先確定傳遞過來7個參數,隨后把其中2個傳遞給merge包裝腳本,默認情況下, Git 傳遞以下參數給diff:
`path old-file old-hex old-mode new-file new-hex new-mode`
由于你僅僅需要old-file和new-file參數,用diff包裝腳本來傳遞它們吧。
~~~
$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"
~~~
確認這兩個腳本是可執行的:
~~~
$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff
~~~
現在來配置使用你自定義的比較和合并工具吧。這需要許多自定義設置:merge.tool通知 Git 使用哪個合并工具;`mergetool.*.cmd`規定命令運行的方式;`mergetool.trustExitCode`會通知 Git 程序的退出是否指示合并操作成功;`diff.external`通知 Git 用什么命令做比較。因此,你能運行以下4條配置命令:
~~~
$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.trustExitCode false
$ git config --global diff.external extDiff
~~~
或者直接編輯`~/.gitconfig`文件如下:
~~~
[merge]
tool = extMerge
[mergetool "extMerge"]
cmd = extMerge \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"
trustExitCode = false
[diff]
external = extDiff
~~~
設置完畢后,運行diff命令:
`$ git diff 32d1776b1^ 32d1776b1`
命令行居然沒有發現diff命令的輸出,其實,Git 調用了剛剛設置的P4Merge,它看起來像圖7-1這樣:

Figure 7-1. P4Merge.
當你設法合并兩個分支,結果卻有沖突時,運行`git mergetool,Git `會調用P4Merge讓你通過圖形界面來解決沖突。
設置包裝腳本的好處是你能簡單地改變diff和merge工具,例如把extDiff和extMerge改成KDiff3,要做的僅僅是編輯extMerge腳本文件:
~~~
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
~~~
現在 Git 會使用KDiff3來做比較、合并和解決沖突。
Git預先設置了許多其他的合并和解決沖突的工具,而你不必設置cmd。可以把合并工具設置為:kdiff3、opendiff、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff。如果你不想用到KDiff3的所有功能,只是想用它來合并,那么kdiff3正符合你的要求,運行:
`$ git config --global merge.tool kdiff3`
如果運行了以上命令,沒有設置extMerge和extDiff文件,Git 會用KDiff3做合并,讓通常內設的比較工具來做比較。
## 格式化與空白
格式化與空白是許多開發人員在協作時,特別是在跨平臺情況下,遇到的令人頭疼的細小問題。由于編輯器的不同或者Windows程序員在跨平臺項目中的文件行尾加入了回車換行符,一些細微的空格變化會不經意地進入大家合作的工作或提交的補丁中。不用怕,Git 的一些配置選項會幫助你解決這些問題。
### core.autocrlf
假如你正在Windows上寫程序,又或者你正在和其他人合作,他們在Windows上編程,而你卻在其他系統上,在這些情況下,你可能會遇到行尾結束符問題。這是因為Windows使用回車和換行兩個字符來結束一行,而Mac和Linux只使用換行一個字符。雖然這是小問題,但它會極大地擾亂跨平臺協作。
Git可以在你提交時自動地把行結束符CRLF轉換成LF,而在簽出代碼時把LF轉換成CRLF。用core.autocrlf來打開此項功能,如果是在Windows系統上,把它設置成true,這樣當簽出代碼時,LF會被轉換成CRLF:
`$ git config --global core.autocrlf true`
Linux或Mac系統使用LF作為行結束符,因此你不想 Git 在簽出文件時進行自動的轉換;當一個以CRLF為行結束符的文件不小心被引入時你肯定想進行修正,把core.autocrlf設置成input來告訴 Git 在提交時把CRLF轉換成LF,簽出時不轉換:
`$ git config --global core.autocrlf input`
這樣會在Windows系統上的簽出文件中保留CRLF,會在Mac和Linux系統上,包括倉庫中保留LF。
如果你是Windows程序員,且正在開發僅運行在Windows上的項目,可以設置false取消此功能,把回車符記錄在庫中:
`$ git config --global core.autocrlf false`
### core.whitespace
Git預先設置了一些選項來探測和修正空白問題,其4種主要選項中的2個默認被打開,另2個被關閉,你可以自由地打開或關閉它們。
默認被打開的2個選項是`trailing-space`和`space-before-tab,``trailing-space`會查找每行結尾的空格,``space-before-tab`會查找每行開頭的制表符前的空格。
默認被關閉的2個選項是`indent-with-non-tab`和`cr-at-eol`,`indent-with-non-tab`會查找8個以上空格(非制表符)開頭的行,`cr-at-eol讓 Git` 知道行尾回車符是合法的。
設置core.whitespace,按照你的意圖來打開或關閉選項,選項以逗號分割。通過逗號分割的鏈中去掉選項或在選項前加-來關閉,例如,如果你想要打開除了cr-at-eol之外的所有選項:
~~~
$ git config --global core.whitespace \
trailing-space,space-before-tab,indent-with-non-tab
~~~
當你運行git diff命令且為輸出著色時,Git 探測到這些問題,因此你也許在提交前能修復它們,當你用git apply打補丁時同樣也會從中受益。如果正準備運用的補丁有特別的空白問題,你可以讓 Git 發警告:
`$ git apply --whitespace=warn <patch>`
或者讓 Git 在打上補丁前自動修正此問題:
`$ git apply --whitespace=fix <patch>`
這些選項也能運用于衍合。如果提交了有空白問題的文件但還沒推送到上游,你可以運行帶有--whitespace=fix選項的rebase來讓Git在重寫補丁時自動修正它們。
## 服務器端配置
Git服務器端的配置選項并不多,但仍有一些饒有生趣的選項值得你一看。
### receive.fsckObjects
Git默認情況下不會在推送期間檢查所有對象的一致性。雖然會確認每個對象的有效性以及是否仍然匹配SHA-1檢驗和,但 Git 不會在每次推送時都檢查一致性。對于 Git 來說,庫或推送的文件越大,這個操作代價就相對越高,每次推送會消耗更多時間,如果想在每次推送時 Git 都檢查一致性,設置` receive.fsckObjects` 為true來強迫它這么做:
`$ git config --system receive.fsckObjects true`
現在 Git 會在每次推送生效前檢查庫的完整性,確保有問題的客戶端沒有引入破壞性的數據。
### receive.denyNonFastForwards
如果對已經被推送的提交歷史做衍合,繼而再推送,又或者以其它方式推送一個提交歷史至遠程分支,且該提交歷史沒在這個遠程分支中,這樣的推送會被拒絕。這通常是個很好的禁止策略,但有時你在做衍合并確定要更新遠程分支,可以在push命令后加-f標志來強制更新。
要禁用這樣的強制更新功能,可以設置~~~
receive.denyNonFastForwards:
~~~
`$ git config --system receive.denyNonFastForwards true`
稍后你會看到,用服務器端的接收鉤子也能達到同樣的目的。這個方法可以做更細致的控制,例如:禁用特定的用戶做強制更新。
### receive.denyDeletes
規避`denyNonFastForwards`策略的方法之一就是用戶刪除分支,然后推回新的引用。在更新的 Git 版本中(從1.6.1版本開始),把receive.denyDeletes設置為true:
`$ git config --system receive.denyDeletes true`
這樣會在推送過程中阻止刪除分支和標簽 — 沒有用戶能夠這么做。要刪除遠程分支,必須從服務器手動刪除引用文件。通過用戶訪問控制列表也能這么做,在本章結尾將會介紹這些有趣的方式。
- 1. 起步
- 1.1 關于版本控制
- 1.2 Git 簡史
- 1.3 Git 基礎
- 1.4 安裝 Git
- 1.5 初次運行 Git 前的配置
- 1.6 獲取幫助
- 1.7 小結
- 2. Git基礎
- 2.1 取得項目的 Git 倉庫
- 2.2 記錄每次更新到倉庫
- 2.3 查看提交歷史
- 2.4 撤消操作
- 2.5 遠程倉庫的使用
- 2.6 打標簽
- 2.7 技巧和竅門
- 2.8 小結
- 3. Git分支
- 3.1 何謂分支
- 3.2 分支的新建與合并
- 3.3 分支的管理
- 3.4 利用分支進行開發的工作流程
- 3.5 遠程分支
- 3.6 分支的衍合
- 3.7 小結
- 4. 服務器上的Git
- 4.1 協議
- 4.2 在服務器上部署 Git
- 4.3 生成 SSH 公鑰
- 4.4 架設服務器
- 4.5 公共訪問
- 4.6 GitWeb
- 4.7 Gitosis
- 4.8 Gitolite
- 4.9 Git 守護進程
- 4.10 Git 托管服務
- 4.11 小結
- 5. 分布式Git
- 5.1 分布式工作流程
- 5.2 為項目作貢獻
- 5.3 項目的管理
- 5.4 小結
- 6. Git工具
- 6.1 修訂版本(Revision)選擇
- 6.2 交互式暫存
- 6.3 儲藏(Stashing)
- 6.4 重寫歷史
- 6.5 使用 Git 調試
- 6.6 子模塊
- 6.7 子樹合并
- 6.8 總結
- 7. 自定義Git
- 7.1 配置 Git
- 7.2 Git屬性
- 7.3 Git掛鉤
- 7.4 Git 強制策略實例
- 7.5 總結
- 8. Git與其他系統
- 8.1 Git 與 Subversion
- 8.2 遷移到 Git
- 8.3 總結
- 9. Git 內部原理
- 9.2 Git 對象
- 9.3 Git References
- 9.4 Packfiles
- 9.5 The Refspec
- 9.6 傳輸協議
- 9.7 維護及數據恢復
- 9.8 總結
- 9.1 底層命令 (Plumbing) 和高層命令 (Porcelain)