安裝Git
Linux
1 2 3 4 5 |
$ sudo yum install git 或者 $ sudo apt-get install git |
Mac
直接在Terminal
執行git
命令, 如果沒有會提示安裝方法.
如果喜歡安裝程式的話, 點這裡
配置檔案
第一次安裝, 千萬別要忘了配置你的git的使用者名字和郵箱. 這個道理很簡單, 每一次的提交時需要記錄提交者的, 如果沒有提交者, 那麼bug出現找誰來背鍋??
檢視config
Git 自帶一個 git config 的工具來幫助設定控制 Git 外觀和行為的配置變數。
1 2 3 4 5 6 7 |
/etc/gitconfig 檔案: 包含系統上每一個使用者及他們倉庫的通用配置。 $ git config --system --list ~/.gitconfig 或 ~/.config/git/config 檔案:只針對當前使用者。 $ git config --global --list |
當前使用倉庫的 Git 目錄中的 config 檔案(就是 .git/config
):針對該倉庫。
每一個級別覆蓋上一級別的配置,所以.git/config
的配置變數會覆蓋/etc/gitconfig
中的配置變數。
當然, 也可以檢視某一項配置資訊.
- 形式:
git config [--global|--system]
1 2 3 4 5 |
檢視最終的配置屬性值 $ git config user.name 檢視當前系統的屬性值 $ git config --global user.name |
設定使用者資訊
1 2 3 |
$ git config --global user.name "name" $ git config --global user.email xxx@163.com |
使用--global
選項, 當以後在該系統上做的任何操作都會使用此屬性. 如果你需要在某一個特定的專案使用其他名字和郵箱, 那麼可以通過設定專案中的config檔案, 這樣config中的屬性會覆蓋掉global的全域性屬性, 並且當在其他專案中並不會造成影響. 使用方式只需要去掉--global
引數即可修改專案中的.git/config
檔案
1 |
$ git config user.name "name" |
獲取幫助手冊
形式: git help
或者 git --help
比如檢視config手冊
1 |
$ git help config |
Git別名
例如: 生成別名之後可以在日後用簡短的表示來使用
1 2 3 |
$ git config --global alias.br branch $ git config --global alias.ci commit $ git config --global alias.st status |
.gitignore檔案
對於自動生成的檔案, 日誌, 編譯的臨時檔案等. 可以對其進行配置, 讓git不追蹤這些檔案
規範如下:
- 所有空行或者以 # 開頭的行都會被 Git 忽略。
- 可以使用標準的 glob 模式匹配。
- 匹配模式可以以(/)開頭防止遞迴。
- 匹配模式可以以(/)結尾指定目錄。
- 要忽略指定模式以外的檔案或目錄,可以在模式前加上驚歎號(!)取反
glob模式
是指shell所使用的簡化了的正規表示式.
*
:匹配零個或多個任意字元[abc]
:只匹配括號內的任意一個字元[0-9]
:使用短劃線表示範圍, 可以匹配0到9之間的任何字元.?
:匹配任意一個字元**
:匹配任意的中間目錄,例如a/**/z
可以匹配a/z
,a/b/z
,a/b/c/z
等
如下給出一個樣板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 忽略所有以 .c結尾的檔案 *.c # 但是 stream.c 會被git追蹤 !stream.c # 只忽略當前資料夾下的TODO檔案, 不包括其他資料夾下的TODO例如: subdir/TODO /TODO # 忽略所有在build資料夾下的檔案 build/ # 忽略 doc/notes.txt, 但不包括多層下.txt例如: doc/server/arch.txt doc/*.txt # 忽略所有在doc目錄下的.pdf檔案 doc/**/*.pdf |
倉庫的基礎操作
初始化倉庫
1 |
$ git init |
新增檔案到暫存區
1 2 3 4 5 6 7 8 |
# 新增全部暫存區和歷史區不存在的或者有更改的 `.c`結尾的檔案 $ git add *.c # 新增全部暫存區和歷史區不存在的或者有更改的檔案 $ git add . # 指定檔案新增 $ git add test.c |
status倉庫
1 2 3 4 |
$ git status # 如果需要顯示一種緊湊式格式 $ git status --short # 等價於 $ git status -s |
緊湊式中字母的表示含義如下:
??
:表示新新增的未追蹤的檔案M
:M出現在右邊,表示該檔案被修改但是還沒有放入暫存區M
:M出現在左邊,表示檔案被修改已經放入了暫存區MM
:出現兩個,代表此檔案在工作區修改已經放入了暫存區, 但之後有進行了修改,沒有新增到暫存區
diff倉庫
如果你想知道檔案具體修改的內容, 那麼diff
會很有用
1 2 3 4 5 |
# 檢視以追蹤但尚未暫存的檔案更新了哪些部分, 不新增額外引數 $ git diff # 對使用了add新增到了暫存區的內容, 使用--staged引數或者--cached $ git diff --staged |
提交更新
1 2 3 4 5 6 7 8 |
# 常規做法 $ git commit -m "commit message" # 如果不使用-m引數新增提交資訊, git會使用預設的編譯器如vi進行提交描述編寫. # 可通過$ git config --global core.edit 設定喜歡的編譯器 # 跳過暫存區操作, 直接從工作區提交到歷史區 $ git commit -a -m "" #等價於: $ git commit -am "" |
移除檔案
如果在工作區間對一個檔案進行刪除, 需要先進行add
,然後才可以提交. 使用git rm
可以直接在工作區間刪除檔案, 並提交到暫存區.
1 2 3 4 5 6 7 8 |
$ git rm fileName # 如果檔案修改,並新增了暫存區, 需要使用-f引數來強制刪除(force) $ git rm -f fileName # 可以使用glob模式,如下 $ git rm log/*.log # 刪除log目錄下所有名稱是.log結尾檔案 $ git rm *~ # 刪除以~結尾的所有檔案 |
移動檔案
同樣使用git rm
會方便很多, 並且如果相對檔案重新命名也可以如此
1 |
$ git mv file_from file_to |
當執行了這條語句之後, 只需要在下一次commit
即可, 不需要考慮額外操作. 等價於如下:
1 2 3 |
$ mv file_from file_to $ git rm file_from $ git rm file_to |
檢視歷史提交
如果是最基本的git log
, 那麼會按提交時間列出所有更新, 包括提交的SHA-1校驗和, 作者名稱,郵箱,提交時間,提交說明. 下面說說常用選項.
1 2 3 4 5 6 7 8 9 10 11 12 |
# -p:僅顯示最近x次的提交 格式 $ git log -p -x $ git log -p -2 # 檢視最近的兩次提交內容 # --stat:簡略的顯示每次提交的內容更改, 如哪些檔案變更,多少刪除,多少新增等 $ git log --stat # --pretty: 指定預設不同格式展示資訊 $ git log --pretty=oneline #每次提交用一行顯示 $ git log --pretty=format:"%h - %an, %ar : %s" # 效果:1a99c42 - 蘇, 19 hours ago : 無意義提交 |
關於format
對應的常用佔位符的寫法和意義
選項 | 說明 |
---|---|
%H | 提交物件(commit)的完整雜湊字串 |
%h | 提交物件的簡短雜湊字串 |
%T | 樹物件(tree)的完整雜湊字串 |
%t | 樹物件的簡短雜湊字串 |
%P | 父物件(parent)的完整雜湊字串 |
%p | 父物件的簡短雜湊字串 |
%an | 作者(author)的名字 |
%ae | 作者的電子郵件地址 |
%ad | 作者修訂日期(可以用 –date= 選項定製格式) |
%ar | 作者修訂日期,按多久以前的方式顯示 |
%cn | 提交者(committer)的名字 |
%ce | 提交者的電子郵件地址 |
%cd | 提交日期 |
%cr | 提交日期,按多久以前的方式顯示 |
%s | 提交說明 |
圖形展示分支的合併歷史
1 |
$ git log --graph --oneline #oneline只是讓輸出看起來比較舒服 |
git log的一些其他操作
選項 | 說明 |
---|---|
-p | 按補丁格式顯示每個更新之間的差異。 |
–stat | 顯示每次更新的檔案修改統計資訊。 |
–shortstat | 只顯示 –stat 中最後的行數修改新增移除統計。 |
–name-only | 僅在提交資訊後顯示已修改的檔案清單。 |
–name-status | 顯示新增、修改、刪除的檔案清單。 |
–abbrev-commit | 僅顯示 SHA-1 的前幾個字元,而非所有的 40 個字元。 |
–relative-date | 使用較短的相對時間顯示(比如,“2 weeks ago”)。 |
–graph | 顯示 ASCII 圖形表示的分支合併歷史。 |
–pretty | 使用其他格式顯示歷史提交資訊。可用的選項包括 oneline,short,full,fuller 和 format(後跟指定格式)。 |
查詢一個字串的出現和刪除的提交
1 2 3 4 5 |
# 使用限制符-S後面緊跟要查詢的字串 $ git log -Smethod_name # 或者針對一個檔案進行更改的提交查詢, 只需要在後面追加檔名稱即可 $ git log fileName |
哈哈,即使如果你不小心寫個隱藏bug不管幾個月之後,如果老大要想找出問題是寫引發的其實很簡單.例如這樣
$ git log -p fileName
想甩鍋?算了吧,還是認錯以後多注意吧.
還有一些限制log輸出的選項
選項 | 說明 |
---|---|
-(n) | 僅顯示最近的 n 條提交 |
–since, –after | 僅顯示指定時間之後的提交。 |
–until, –before | 僅顯示指定時間之前的提交。 |
–author | 僅顯示指定作者相關的提交。 |
–committer | 僅顯示指定提交者相關的提交。 |
–grep | 僅顯示含指定關鍵字的提交 |
-S | 僅顯示新增或移除了某個關鍵字的提交 |
一個實際的例子,如果要檢視 Git 倉庫中,2016 年 11 月1號到7號,作者叫蘇的提交檔案,可以用下面的查詢命令:
1 2 |
git log --pretty="%h - %s" --author=蘇 --since="2016-11-01" --before="2016-11-07" |
撤銷操作
amend重新提交
當我們commit
之後突然發現漏掉了一個檔案, 這個時候不可能對一個檔案再進行commit
一次, 這樣做就顯得很多餘, 而如果版本回退之前再新增也比較麻煩. 這個時候就可以使用這個amend
命令.如下:
1 2 3 4 5 6 |
$ git commit -m "版本1.5開發程式碼" # 正當你鬆了一口氣的時候發現配置檔案忘記修改了, 你趕緊修改,並適合用add到暫存區 $ git add project.property $ git commit --amend # 你會神奇的發現你沒有增加任何多餘的操作就把漏掉的檔案補齊到最後一次提交中 |
取消暫存的檔案
就是對檔案進行了git add
操作. 這個時候可以reset
1 2 |
# 讓暫存區的檔案變成檔案修改但是沒有新增暫存區的狀態 $ git reset HEAD fileName |
撤銷對檔案的修改
場景: 當檔案修改了, 但是還沒有進行git add
的時候還只是在工作區間, 還原成最後一次提交的內容
1 |
$ git checkout -- filename |
要注意使用, 使用之前確定是否要拋棄已經新增的內容. 因為這個動作可能讓你最新新增的內容徹底丟失. 因為沒有進行commit
, 一般來說進行了commit
的內容都是可以恢復的.
標籤
Git可以給歷史中的某一個提交打上標籤, 以示重要. 比如每次正式版本的上線等.
列出標籤
1 2 3 4 |
$ git tag # 如果你只關心某一部分的標籤, 例如只對v2.x的標籤感興趣,你可以這樣做 $ git tag -l 'v2.*' |
建立標籤
標籤分為兩種一種是附加標籤
另一種是輕量標籤
.
- 附加標籤: 會儲存打標籤者的資訊, 時間和附加資訊. 最後更隨打標籤的提交
- 輕量標籤: 只是在一個提交上做一個標記. 儲存在一個專門儲存標籤的檔案,指向提交的hash值
先來看附加標籤:
1 |
$ git tag -a v1.0 -m '附加資訊' |
輕量標籤
1 |
$ git tag v1.0 |
後期打標籤, 就是對已經提交某次提交進行追加標籤設定
1 2 3 4 5 |
# 可以先使用git log --oneline獲取提交歷史的hash值 $ git log --oneline # 然後把hash值賦值到標籤語句之後 $ git tag -a v1.1 a6b4c97 |
共享標籤
預設情況下, git push
不會把標籤傳遞到遠端伺服器. 需要顯示的推送標籤共享到伺服器
例如: git push origin [tagname]
1 2 3 4 |
$ git push origin v1.4 # 如果想把本地上所有在遠端伺服器上的不存在標籤刪除掉,可以這樣 $ git push origin --tags |
檢出標籤
git中不能真正的檢出一個標籤, 但是可以在標籤處建立一個新的分支.如下
1 |
$ git checkout -b checkbranch2 v2.0 |
檢視標籤對應的資訊
使用git show
可以檢視對應標籤的詳細資訊, 如果git show
這樣的命令只是顯示上次提交的內容
1 |
$ git show v1.4 |
分支操作
分支的建立
分支的建立, 其實本質就是建立一個可以移動的指標,這個指標名就是新的分支名
1 2 3 4 5 6 7 8 9 10 |
$ git branch dev # 上面的只是建立了一個分支. 並沒有切換, 可以使用一條命令建立並且換到新分支 $ git checkout -b dev # 可以通過`git log`命令檢視各個分支所指向的物件 $ git log --oneline --decorate # 如果你想檢視圖形式的分叉歷史,可以這樣: $ git log --oneline --decorate --graph --all |
分支的切換
所謂的分支切換就是HEAD
指標的指向的改變
1 |
$ git checkout dev |
分支合併
利用git merge
, 這條命令會把當前所在分支與目標分支的內容合併, 可以這樣理解, 如果當你試圖向目標分支合併時, 如果當前分支可以順著一個分支走下去, 那麼本質上其實只是當前指標的向前移動, 由於這種情況下的合併並沒有需要解決的分期, 所以git會稱這個是fast-forward
快速前進.
1 |
git merge dev |
刪除分支
當一個功能分支開發完畢之後, 並進行了合併, 通常這個分支也就被刪除,以保證倉庫中的乾淨.
1 2 3 4 5 |
# 刪除dev分支 $ git branch -d dev # 如果dev分支還有未提交的內容,為了保證你的資料安全git預設是不允許刪除,可以使用`-D`強制刪除 $ git branch -D dev |
分支管理
git branch
命令不只是可以建立於刪除分支. 如果不新增任何引數, 那麼會得到所有分支的一個列表
1 2 3 4 5 6 7 8 9 10 |
$ git branch # 其中一個分支前面的*代表,目前檢出的分支就是HEAD指標所指向的分支 # 追加-v引數 可以展示每一個分支最後一次提交 $ git branch -v # --merged:檢視那些分支已經合併到當前分支 $ git branch --merged # 一般這個列表展示的除了*號的其他分支, 都可以刪除 # --no-merged:檢視所有包含未合併工作的分支 $ git branch --no-merged |
變基
和合並
merge
相似的效果都是合併分支, 但是使用變基rebase
可以讓提交歷史變得更簡潔. 如下
圖片1是merge
合併效果, 圖片2是rebase
合併效果. 明顯變基會讓提交歷史看起來更加乾淨. 使用如下:
1 2 3 4 5 6 |
# rebase [需要移動變基底的分支] $ git rebase master experiment # 此時目標分支後面會追加另一個分支的提交. 此時只需要切換到master分支,合併分支即可. $ git checkout master $ git merge experiment |
rebase
原理就是, 從目標分支和要變基的分支向上查詢出共同祖先節點就是c2
, 然後把要變基的分支到c2
節點的所有提交,提取出相應的修改生成一個副本, 並追加到目標分建立相對應的提交. 此時變基的分支指向目標分支master
的後面某一次提交. 此時只要使用修改master
指向指標使用merge
即可.
遠端分支
1 2 3 4 5 6 7 8 |
# 獲得遠端的倉庫列表 $ git ls-remote origin # 如果想獲得更多的資訊 $ git remote show origin # 檢視遠端分支和本地分支 $ git branch -a |
拉取遠端分支
假設遠端如果有一個dev
分支, 你使用fetch
進行抓取. 這個時候, 本地不會自動生成一個可編輯的副本, 換句話說就是這種情況下, 不會有一個新的dev
本地分支, 只有一個不可以修改的origin/dev
指標. 這個時候可以執行git merge origin/dev
命令, 將這些遠端dev分支的工作合併到當前分支. 如果想要在自己本地的dev分支上工作, 可以將其建立在遠端分支之上.
1 |
$ git checkout -b dev origin/dev |
建立遠端分支
如果你的本地有一個新建的dev
分支, 並且你進行了提交, 此時你想把這個分支也提交到遠端的dev
分支, 但是遠端還沒有建立dev
, 這個時候可以使用如下命令: git push
1 |
$ git push origin dev |
刪除遠端分支
1 2 |
# 刪除遠端dev分支 $ git push origin --delete dev |
跟蹤分支
從一個遠端跟蹤分支檢出一個本地分支會自動建立一個叫做 跟蹤分支
(有時候也叫做 “上游分支”)。 跟蹤分支是與遠端分支有直接關係的本地分支。 如果在一個跟蹤分支上輸入git pull
,Git
能自動地識別去哪個伺服器上抓取、合併到哪個分支。
當克隆一個倉庫時,它通常會自動地建立一個跟蹤 origin/master
的 master
分支。 然而,如果你願意的話可以設定其他的跟蹤分支 – 其他遠端倉庫上的跟蹤分支,或者不跟蹤 master
分支。 最簡單的就是之前看到的例子,執行 git checkout -b [branch] [remotename]/[branch]
。 這是一個十分常用的操作所以 Git 提供了 --track
快捷方式:
1 2 3 4 |
$ git checkout --track origin/dev # 如果想要自定義本地分支名字 $ git checkout -b 任意分支名字 origin/dev |
設定已有的本地分支跟蹤一個剛剛拉取下來的遠端分支,或者想要修改正在跟蹤的上游分支,你可以在任意時間使用 -u 或 –set-upstream-to 選項執行 git branch 來顯式地設定。
1 2 |
# 設定HEAD指向的分支的上游為遠端dev分支 $ git branch -u origin/dev |
檢視設定的所有跟蹤分支
1 |
$ git branch -vv |
遠端倉庫操作
克隆倉庫
1 2 3 4 |
$ git clone # 如果你想建立自己的倉庫名, 就是本地根資料夾的名稱, 那麼可以如下追加名稱 $ git clone [dirName] |
檢視遠端倉庫
1 2 3 4 5 |
# 預設檢視遠端倉庫的方式 $ git remote # 檢視遠端倉庫的讀寫許可權. 如果可以看到(push)說明提交的推送 $ git remote -v |
如果需要檢視某一個倉庫更多的資訊時, 使用git remote show ...
1 |
$ git remote show origin |
新增遠端倉庫
1 2 3 4 5 |
# 格式: git remote add [shortName] 同時可以指定一個倉庫的引用名稱,例如 $ git remote add rp git@github.com:suzeyu1992/GitOperateDemo.git # 此時你想對新加的遠端進行拉取動作, 只需要使用之前的引用名稱就可以 $ git fetch rp |
遠端倉庫的拉取推送
拉取
大家常用的可能是git pull
這個指令. 這個指令的通常會從伺服器上抓取資料自動嘗試合併到當前所在分支.
而我們可以也可以利用git fetch
進行本地分支所追蹤的遠端分支沒有提交. 然後我們可以手動的進行合併.
推送
git push [remote-name] [branch-name]
例如:
1 |
$ git push origin master |
只有當對伺服器有寫入許可權, 並且之前沒有人提交, 這條命令才會生效.
上面的這兩個推送也好拉取也好. 如果所在分支設定了遠端伺服器分支的追蹤, 那麼可以省略掉後面的倉庫名和分支名. 如果沒有設定那麼必須顯示的指定.
遠端倉庫移除重新命名
對遠端倉庫的名稱進行修改
1 |
$ git remote rename oldName newName |
想要移除一個遠端倉庫,例如伺服器搬走了,不再使用一個特定映象,或者一個貢獻者不再貢獻
1 |
$ git remote rm 倉庫名 |