git cat-file (-t|-s|-p) object 顯示 object 的大小,類型,以及內容.git
-t 顯示 object 的類型.commit,tag,tree,blob.shell
-s 顯示 object 的大小,字節爲單位.編輯器
-p 顯示 object 的內容.工具
git branch [-r] 默認狀況下,僅顯示當前本地擁有的分支.fetch
-r 僅顯示本地保存的遠程版本庫的分支列表.優化
git branch <branchName> [<commit>] [--track] 新建一個分支.ui
commit 指定了新建分支 branchName 引用的 commit object,默認爲 HEAD.url
--track 若 commit 經過一個分支指定,則將 branchName 與 commit 創建追蹤(分支追蹤,見下).spa
git branch (-d|-D) [-r] <branchName> 刪除分支3d
-d 若 branchName 已經與其餘分支合併,則刪除該分支.不然不執行刪除操做.
-D 老是刪除分支 branchName.
-r 代表 branchName 爲遠程版本庫分支,此時將從本地移除遠程版本庫分支 branchName.
$ git branch -r origin/Branch origin/Branch1 origin/HEAD -> origin/master origin/master $ git branch -d -r origin/master 已刪除遠程分支 origin/master (曾爲 53bcdd3).
git branch (-m|-M) <oldBranchName> <newBranchName> 將分支 oldBranchName 重命名爲 newBranchName.
-m 若 newBranchName 已經存在,則拒絕執行重命名操做.
-M 強制重命名,總會執行重命名操做.
# 將本地分支 master 與遠程版本庫 origin 的 heads/master 分支創建追蹤. [branch "master"] remote = origin # 遠程版本庫名. merge = refs/heads/master # 遠程版本庫分支. # 將本地分支 test 與本地分支 master 創建追蹤. [branch "test"] remote = . # 代表本地版本庫 merge = refs/heads/master # 參見 git push/git pull 對以上配置項的使用
git tag -nN 顯示當前擁有的標籤列表.
-nN 對於每個標籤,顯示最多 N 行的標籤註釋.若標籤爲輕量級標籤,則顯示標籤指向 commit object 的註釋.
git tag (-a|-m <message>) [-f] <tagName> [<commit>] 建立一個重量級標籤 tagName.
-a 此時打開默認的編輯器來輸入標籤 tagName 的註釋.
-m <message> 此時將標籤 tagName 的註釋指定爲 message.
-f 當 <tagName> 已經存在時,仍強制建立標籤.此時效果至關於更新原有的 <tagName> 標籤
commit 指定了標籤關聯的 commit object,默認爲 HEAD.
git tag [-f] <tagName> [<commit>] 建立一個輕量級標籤 tagName.
-f 當 <tagName> 已經存在時,仍強制建立標籤.此時效果至關於更新原有的 <tagName> 標籤
git tag -d <tagName> 移除標籤 tagName,標籤在 .git/logs/ 下並無對應的日誌文件,因此一旦刪除,不易恢復.
$ git tag -d Qing 已刪除 tag 'Qing' (曾爲 91d5974) # Qing 爲輕量級標籤,因此此時輸出的是標籤對應的 commit object 的 SHA1 值. $ git tag -d Zhong 已刪除 tag 'Zhong' (曾爲 8898195) # Zhong 爲重量級標籤,因此此時輸出的是 tag object 自身的 SHA1 哈希值. # 刪除標籤後,惟一的恢復方法: 就是利用 git tag -d 的輸出從新建立標籤.
git add [options] 將工做區中新建或者修改後的文件添加到暫存區中.options 可取值:
-u 對已經加入到暫存區而且修改的文件調用 git add,對已經加入到暫存後但被刪除的文件調用 git rm .
-A 等同於 -u,只不過 -A 會對未加入到暫存區的文件也調用 git add 操做.
-v 詳細的輸出.
-f 強制添加被忽略的文件.
注意:
當調用 git add 向暫存區添加新的文件,而後調用 git rm 從暫存區刪除文件(或者先調用 git rm,而後再調用 git add),此時暫存區就會比較被刪除文件的內容與新增文件的內容,而後根據差別結果來判斷這到底是一個重命名操做,仍是添加,刪除操做.如:
$ cp README ReadMe $ git status -s ?? ReadMe # ReadMe 未被追蹤. $ git rm README rm 'README' # 從暫存區/工做區中移除 README $ git status -s D README ?? ReadMe $ git add ReadMe # 將 ReadMe 添加到暫存區中. $ git status -s # 能夠檢測到這是一個重命名操做. R README -> ReadMe
git cherry-pick <commit> 應用提交 commit.此時 git cherry-pick 的行爲:
生成 commit->commit object->tree object 相對於 commit^->commit object->tree object 的差別文件.即生成 commit 目錄樹相對於其父提交目錄樹的差別文件.關於
在當前工做區引用該差別文件.
更新暫存區,
建立一個新的提交.
當發生衝突時,停留在第 2 步,此時要作的就是:
打開引發衝突的文件,並修正衝突(詳見 git merge)
手動完成第 3,4 步.
git revert commit 反轉提交 commit.此時 git revert 的行爲:
生成 commit^->commit object->tree object 相對於 commit->commit object->tree object 的差別文件,即生成 commit 父提交目錄樹相對於 commit 目錄樹的差別文件.
同 git cherry-pick 的第 2,3,4 步.
當發生衝突時,停留在第 2 步,此時要作的就是:
打開引發衝突的文件,並修正衝突(詳見 git merge)
手動完成第 3,4 步.
git rebase --onto <newBase> <since> <till> 變基,此時行爲:
git checkout till ;切換到 till,因此 git rebase 後可能會處於分離頭指針狀態.
將 (since,till] 所包含的提交範圍寫入一個臨時文件中,
git reset --hard newBase;
git cherry-pick 應用 (since,till] 所包含的提交.
當變基遇到衝突後(即 git cherry-pick 遇到衝突時),則在修正衝突後,能夠:
git rebase --continue ,繼續變基.
git rebase --skip ,跳過此提交.
git rebase --abort,就此終止變基操做並切換到變基前的分支.
git commit-tree [(-p <parent>)...] [(-m <message>)...] [(-F <file>)...] <tree> 基於 tree 指定的 tree object 建立一個 commit object.
-p 指定該 commit object 的父提交對象,能夠指定多個,若不指定 -p,則新建的 commit object 沒有父提交,能夠看成根提交.
-m <message> 指定提交說明,能夠爲多個.此時每個 <message> 佔據一個段落.
-F <file> 從 <file> 中讀取提交說明.若 <file> 爲'-',則代表從標準輸入中讀取提交說明.
$ echo "你好 "|git commit-tree -m "Hello" -m "World" -F - HEAD^{tree} f02feca314fe4570293ed1ab0e257b3f5898889b # 新建 commit object 的 SHA1 值 $ git cat-file -p f02feca tree 0ee5a125454857f41e45a586cb87621844cfa725 author WangXiaoWei <1258941862@qq.com> 1401697344 +0800 committer WangXiaoWei <1258941862@qq.com> 1401697344 +0800 Hello # 一個 -m 佔據一個段落 World 你好 # -F 能夠與 -m 一同指定
git clone [--bare|--mirror] <repository> <directory> 將版本庫 repository 克隆到目錄 directory 中.
--bare 將版本庫<repository>克隆到一個裸版本庫中,此時<directory>的名稱通常之後綴 .git 結尾.
--mirror 與 --bare 的不一樣就是見下,如:
$ git clone Git/ Git_bare.git --bare $ git clone Git/ Git_mirror.git --mirror $ git diff Git_bare.git/ Git_mirror.git/ diff --git a/Git_bare.git/config b/Git_mirror.git/config index 96b01bf..86dc706 100644 --- a/Git_bare.git/config +++ b/Git_mirror.git/config @@ -4,3 +4,5 @@ bare = true [remote "origin"] url = /root/CCProject/Git/ + fetch = +refs/*:refs/* + mirror = true # --mirror 對 repository 進行了註冊. diff --git a/Git_bare.git/packed-refs b/Git_mirror.git/packed-refs index 72f6723..3125a54 100644 --- a/Git_bare.git/packed-refs +++ b/Git_mirror.git/packed-refs @@ -1,5 +1,11 @@ pack-refs with: peeled fully-peeled e156455ea49124c140a67623f22a393db62d5d98 refs/heads/master +e156455ea49124c140a67623f22a393db62d5d98 refs/remotes/origin/HEAD +eea591373e139fc8aab89a78ccb0b1512a2bf0de refs/remotes/origin/maint +e156455ea49124c140a67623f22a393db62d5d98 refs/remotes/origin/master +5318336450357c9ecf6ffed2ca846e4c22dbfb7c refs/remotes/origin/next +2c23f4020ee1398f929c3781c88e9446e28482a4 refs/remotes/origin/pu +aa5f59252760682ebd536e08b83b70792890ee5a refs/remotes/origin/todo d5aef6e4d58cfe1549adef5b436f3ace984e8c86 refs/tags/gitgui-0.10.0 ^3d654be48f65545c4d3e35f5d3bbed5489820930 33682a5e98adfd8ba4ce0e21363c443bd273eb77 refs/tags/gitgui-0.10.1 # --mirror 同時將遠程分支也克隆下來.. # 好吧,... --bare 與 --mirror 具體差別我不是很清除.
git push [remote-repository] <引用表達式> 將本地引用上傳到遠程版本庫,此時行爲:
string remoteName,remoteUrl,refexp; if(branch.currentBranch.remote 存在 && 不爲空) /* 肯定遠程版本庫名. */ remoteName=branch.currentBranch.remote; else remoteName=origin; if(remote.remoteName.pushurl 存在 && 不爲空) /* 肯定遠程版本庫的 url */ remoteurl=remote.remoteName.pushurl; else remoteurl=remote.remoteName.url; if(remote.remoteName.push 存在 && 不爲空) /* 肯定引用表達式 */ refexp=remote.remoteName.push else refexp=":"; /* 同名分支推送. */
引用表達式: local-ref:remote-ref.共有如下幾種狀況:
local-ref:remote-ref 將本地引發 local-ref 上傳爲遠程版本庫引用 remote-ref.
:remote-ref 將一個空值推送到遠程版本庫對應的引用.至關於刪除遠程版本庫對應的引用.
: 同名分支推送,即對全部在遠程版本庫中有同名分支的本地分支執行推送.
-f 強制執行非快進式提交
# 遠程版本庫有分支: b1,b2,b3,b4,master # 本地版本庫有分支: b1,b2,b3_3,b4_4,master 本地版本庫$ git push origin : To ../git1/ f166127..d68d8ef b2 -> b2 421c365..e61d632 b1 -> b1 e21a307..57a8ab4 master -> master # 即僅上傳了 b1,b2,master 分支.由於他們在遠程版本庫中存在同名分支. 本地版本庫$ git push origin :b3 To ../git1/ - [deleted] b3 # 遠程版本庫中 b3 分支被移除了. 遠程版本庫$ git branch b1 b2 b4 * master
git pull [遠程版本庫] [引用表達式] [--rebase] 等同於 git fetch 與 git merge/git rebase,即首先將遠程版本庫 remote-repository 上的 local-ref 引用下載下來,而後在當前分支執行變基或者合併操做.行爲:
/* 當調用 git pull,而且沒有指定任何參數時的行爲: */ string remoteName,remoteUrl,refexp; remoteName=branch.currentBranch.remote 存在 && 不爲空 ? branch.currentBranch.remote : origin; /* 肯定遠程版本庫名. */ remoteUrl=remote.remoteName.url;/* 肯定遠程版本 url */ refexp=remote.remoteName.fetch; /* 肯定引用表達式 */ git fetch remoteName refexp; /* 調用 git fetch 取得遠程版本庫引用 */ if(branch.currentBranch.merge 存在 && 不爲空) if(branch.currentBranch.rebase==true || 指定了 --rebase 選項) git rebase;/* TODO(此時不是很清除) */ else git merge branch.currentBranch.merge; else 出錯.
git fetch [--no-tags] [remoteRepository] [+][<引用表達式>] 將遠程版本庫 remoteRepository 的引用下載下來.
--no-tags 不下載 tag object,以及 remoteRepository 中 .git/refs/tags 下全部標籤引用.
引用表達式,同 git push
git merge [--no-commit] <commit> 將<commit>指向的目錄樹與 HEAD 指向的目錄樹合併.此時行爲:
生成 commit->tree object 相對於 HEAD->tree object 的差別文件
在工做區應用該差別文件,此時會新建/移除某些文件,而且可能修改某些文件
更新暫存區
建立一個新的提交
--on-commit 則不執行最後一步,即不建立新的提交.
若在合併過程當中發生衝突,則:
修改引發衝突的文件,而後調用 git add,再 git commit.
因爲文件名修改而致使的衝突.如在提交 A 上重命名: readme->README,在提交 B 上重命名: readme->ReadMe.則將 A 與 B 合併時就會遭遇樹衝突,此時執行 git merge 會提示信息:衝突(重命名/重命名): 在分支 "HEAD" 中重命名 "readme"->"ReadMe",在分支 "XXX" 中重命名 "readme"->"README".修改方式:
$ git status 位於分支 master 您有還沒有合併的路徑.未合併的路徑(酌情使用 "git add/rm <file>..." 標記解決方案): 由他們添加: README 雙方刪除: ReadMe 由咱們添加: readme $ git rm README ReadMe # 即決定保留 readme. README: needs merge ReadMe: needs merge rm 'README' rm 'ReadMe' $ git status 位於分支 master 您有還沒有合併的路徑.未合併的路徑(使用 "git add <file>..." 標記解決方案): 由咱們添加: readme $ git add readme $ git status 位於分支 master 全部衝突已解決但您仍處於合併中。 (使用 "git commit" 結束合併)
git mergetool 調用圖形化工具完成合並.
git init [--bare] [dir] 在目錄 dir 下初始化一個空的版本庫.即建立 .git 目錄.dir 的默認值爲當前目錄.
--bare 初始化一個裸版本庫.
git fsck [--no-reflogs] 顯示未被任何引用文件引用的 git object,就像引用記數中,顯示引用記數爲0的 git object.
--no-reflogs 不考慮 .git/logs/ 中的引用文件.
$ git reset --hard HEAD^ $ git fsck # 由於被重置的提交仍被 HEAD@{1} 引用. Checking object directories: 100% (256/256), done. $ git fsck --no-reflogs Checking object directories: 100% (256/256), done. dangling commit 4967ff2f88d0f2ad9b8840b4921581be9328cf2e # 不考慮 .git/logs 下的引用,則該 commit object 未與任何引用關聯.
git gc [--aggressive] [--auto] [--no-prune] 執行打包,以及清除未被任何引用引用的 git object,以優化 .git 版本庫所佔內存以及存儲效率,此時 git gc 的行爲:
if(gc.packrefs == true) 打包全部的引用 ; git reflog expire --all; /* 清除已通過期的引用日誌,即已經存在 90 天的引用日誌 */ 打包鬆散對象; /* 不會打包未被任何引用關聯的鬆散對象 */ 清除已經存在 2 周的鬆散對象; /* 由於此時若 git object 仍以鬆散對象形式存在,則說明該 object 未被任何引用引用. */
--aggressive 將致使 git gc 以更多的時間爲代價來優化存儲庫.而且優化的效果是持久的.
--auto 通常某些命令在執行完自身任務後會自動調用 git gc --auto.行爲以下:
if(git.auto!=0 && 鬆散對象的數量 > git.auto) 將鬆散對象打包進一個單一的包中. if(git.autopacklimit!=0 && 包的數量 > git.autopacklimit) 將全部的包(除了那些標有保留的包,those marked with a .keep file)打包進一個單一的包中. 退出.
--no-prune 不清除未被任何引用引用的 git object.
遠程版本庫在本地的記錄,是記錄在 .git/config 配置文件中的,以下; git remote 命令實際上就是修改 .git/config 文件,如 git remote set-url remote url.至關於 git config remote.remote.url url.
[remote "hello-world"] # 以'hello-world'爲名註冊一個遠程版本庫. url = /root/GitShared.git/ # 參見 git pull/git push. fetch = +refs/heads/*:refs/remotes/origin/* # 參見 git pull pushurl = /root/GitShared.git/ # 參見 git push.
git remote add [--no-tags] remoteName remoteUrl 添加一個遠程版本庫 remoteName,其 url 爲 remoteUrl.
--no-tags 不會將該遠程版本庫的標籤引入到本地版本庫,即調用 git fetch 時,不會下載 tag object 以及 refs/tags/ 下全部引用文件.
git remote set-url [--push] remoteName url 更改遠程版本庫 remoteName 的 url.即修改 remote.remoteName.url 的取值.
--push 此時修改的是 remote.remoteName.pushurl 的取值
git remote rename oldRemoteName newRemoteName 對遠程版本庫重命名: oldRemoteName->newRemoteName
git remote update 遍歷版本庫列表,對於 remote.<版本庫名>.skipDefaultUpdata 不爲真的版本庫調用 git fetch.
git remote rm remoteName 移除名爲 remoteName 的遠程版本庫.