本文使用命令和命令的基本含義做爲標題,旨在快速查找經常使用命令。git
Git 自帶一個 git config
的工具來幫助設置配置文件。github
這些變量存儲在三個不一樣的位置:web
$ git config --system |
$ git config --global |
當前使用倉庫的 Git 目錄中的 $ git config --local |
咱們也能夠不加參數表明從全部配置文件讀寫文件。app $ git config |
每個級別覆蓋上一級別的配置,覆蓋關係爲local > global > system.ssh
下面舉個例子:maven
-- 查看系統配置文件 $ git config --system --list -- 查看用戶配置文件 $ git config --global --list -- 查看項目配置文件 $ git config --local --list -- 查看全部配置文件 $ git config --list
此命令能夠配合配置文件標識查看不一樣級別配置文件內容編輯器
-- 查看系統配置文件 $ git config --system --list -- 查看用戶配置文件 $ git config --global --list -- 查看項目配置文件 $ git config --local --list -- 查看全部配置文件 $ git config --list
此命令用於修改配置文件內容。
可使用配置文件標識修改指定配置文件內容。
$ git config --global user.name "lic"
通常咱們總會有些文件無需歸入 Git 的管理,也不但願它們總出如今未跟蹤文件列表。 一般都是些自動生成的文件,好比日誌文件,或者編譯過程當中建立的臨時文件等。 在這種狀況下,咱們能夠建立一個名爲.gitignore
的文件,列出要忽略的文件模式。
例子忽略了IDEA、maven、日誌和svn生成的文件。
# --> IDEA .idea/ *.iml # --> maven target/ # --> log logs/ # --> svn .svn/
使用此命令能夠獲取到git關於此命令的幫助手冊
$ git help config
若是你打算使用 Git 來對現有的項目進行管理,你只須要進入該項目目錄並輸入
$ git init
該命令將建立一個名爲 .git
的子目錄,這個子目錄含有你初始化的 Git 倉庫中全部的必須文件,這些文件是 Git 倉庫的骨幹。
「.git」目錄中的文件結構以下
$ ls config description HEAD hooks/ info/ objects/ refs/
config | git配置文件 |
description | 倉庫的描述信息,主要給gitweb等git託管系統使用 |
HEAD | 這個文件包含了一個檔期分支(branch)的引用 |
hooks/ | 這個目錄存放一些shell腳本,能夠設置特定的git命令後觸發相應的腳本;在搭建gitweb系統或其餘git託管系統會常常用到hook script |
info/ | 包含倉庫的一些信息 |
objects/ | 全部的Git對象都會存放在這個目錄中,對象的SHA1哈希值的前兩位是文件夾名稱,後38位做爲對象文件名 |
refs/ | 這個目錄通常包括三個子文件夾,heads、remotes和tags,heads中的文件標識了項目中的各個分支指向的當前commit |
這是個多功能命令:能夠用它開始跟蹤新文件,或者把已跟蹤的文件放到暫存區,還能用於合併時把有衝突的文件標記爲已解決狀態等。 將這個命令理解爲「添加內容到下一次提交中」而不是「將一個文件添加到項目中」要更加合適。
放在項目目錄下的文件默認狀況下是不受Git管理的,你可經過 git add
命令來實現對指定文件的跟蹤。
-- 添加某個文件 $ git add README.md -- 添加所有文件(.爲通配符) $ git add .
若是你想得到一份已經存在了的 Git 倉庫的拷貝,這是就要使用此命令。
這是 Git 區別於其它版本控制系統的一個重要特性,Git 克隆的是該 Git 倉庫服務器上的幾乎全部數據,而不是僅僅複製完成你的工做所須要文件。 當你執行 git clone
命令的時候,默認配置下遠程 Git 倉庫中的每個文件的每個版本都將被拉取下來。 事實上,若是你的服務器的磁盤壞掉了,你一般可使用任何一個克隆下來的用戶端來重建服務器上的倉庫
Git 支持多種數據傳輸協議。 https://
協議、 git://
協議以及SSH協議。使用SSH協議時須要在遠程倉庫配置本機公鑰才能生效。
-- https協議 git clone https://git.oschina.net/imlichao/git-example.git -- SSH協議 git clone git@git.oschina.net:imlichao/git-example.git
要查看哪些文件處於什麼狀態,能夠用此命令。
$ git status
提示主要有一下幾部份內容:
-- 所在分支和跟蹤分支 On branch dev_5.2 Your branch is up-to-date with 'origin/dev_5.2'. -- 沒有文件變動 nothing to commit, working tree clean -- 未被Git管理文件(能夠git add添加跟蹤) Untracked files: (use "git add <file>..." to include in what will be committed) documents/new_file nothing added to commit but untracked files present (use "git add" to track) -- 沒有提保存暫存區的文件(能夠git add保存到暫存區、git checkout放棄修改、git commit -a直接提交) Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: README.md no changes added to commit (use "git add" and/or "git commit -a") -- 暫存區未提交的文件(能夠git reset HEAD返回工做區) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md -- 未推送到遠程分支的提交數量(能夠git push推送到遠程分支) On branch dev_5.2 Your branch is ahead of 'origin/dev_5.2' by 1 commit. (use "git push" to publish your local commits) nothing to commit, working tree clean
git status
命令的輸出十分詳細,但其用語有些繁瑣。 若是你使用 git status -s
命令或 git status --short
命令,你將獲得一種更爲緊湊的格式輸出。 運行 git status -s
,狀態報告輸出以下:
$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
新添加的未跟蹤文件前面有 ??
標記,新添加到暫存區中的文件前面有 A
標記,修改過的文件前面有 M
標記。 你可能注意到了 M
有兩個能夠出現的位置,出如今右邊的 M
表示該文件被修改了可是還沒放入暫存區,出如今靠左邊的 M
表示該文件被修改了並放入了暫存區。 例如,上面的狀態報告顯示: README
文件在工做區被修改了可是尚未將修改後的文件放入暫存區,lib/simplegit.rb
文件被修改了並將修改後的文件放入了暫存區。 而 Rakefile
在工做區被修改並提交到暫存區後又在工做區中被修改了,因此在暫存區和工做區都有該文件被修改了的記錄。
咱們要比較工做區、暫存區以及倉庫分支中文件的差別時可使用此命令。
下面的命令若是不加<file name>表示比較全部文件差別
$ git diff README.md
$ git diff dev_5.2 README.md
$ git diff --cached README.md
和--cached同樣兩種方式一種效果
$ git diff --staged README.md
$ git diff --cached master README.md
$ git diff dev_5.2 master README.md
如今的暫存區域已經準備穩當能夠提交了。 在此以前,請必定要確認還有什麼修改過的或新建的文件尚未git add
過,不然提交的時候不會記錄這些還沒暫存起來的變化。 這些修改過的文件只保留在本地磁盤。 因此,每次準備提交前,先用 git status
看下,是否是都已暫存起來了, 而後再運行提交命令 git commit
git commit
這種方式會啓動文本編輯器以便輸入本次提交的說明。(提交說明必需要填)
咱們也能夠直接使用 -m 參數直接填寫說明
git commit -m "commit explain"
儘管使用暫存區域的方式能夠精心準備要提交的細節,但有時候這麼作略顯繁瑣。 Git 提供了一個跳過使用暫存區域的方式, 只要在提交的時候,給 git commit
加上 -a
選項,Git 就會自動把全部已經跟蹤過的文件暫存起來一併提交,從而跳過 git add
步驟:
$ git commit -a
要從 Git 中移除某個文件,就必需要從已跟蹤文件清單中移除(確切地說,是從暫存區域移除),而後提交。 能夠用 git rm
命令完成此項工做,並連帶從工做目錄中刪除指定的文件,這樣之後就不會出如今未跟蹤文件清單中了。
$ git rm documents/test
因爲git rm是從暫存區域移除,回退操做要使用git reset HEAD從暫存區撤銷,再用git checkout -- 恢復工做區文件。若是已經提交可使用git reset進行回退。
-- 已刪除文件恢復到工做區 $ git reset HEAD documents/test Unstaged changes after reset: D documents/test
-- 已刪除文件恢復到暫存區 $ git checkout -- documents/test
文件file path移動到path目錄。
$ git mv documents/new ./
文件名從file name更改成new name
$ git mv new new1
實際上至關於執行了如下操做
$ mv README.md README $ git rm README.md $ git add README
默認不用任何參數的話,git log
會按提交時間列出全部的更新,最近的更新排在最上面。 正如你所看到的,這個命令會列出每一個提交的 SHA-1 校驗和、做者的名字和電子郵件地址、提交時間以及提交說明。
此命令展現提交歷史時附帶內容差別
$ git log -p
展現提交歷史時附帶統計信息。如那個文件變化幾行,增長內容仍是減小內容等信息。
git log --stat
這個選項能夠指定使用不一樣於默認格式的方式展現提交歷史。 這個選項有一些內建的子選項供你使用。 好比用 oneline
將每一個提交放在一行顯示,查看的提交數很大時很是有用。 另外還有 short
,full
和 fuller
能夠用,展現的信息或多或少有些不一樣,請本身動手實踐一下看看效果如何。
$ git log --pretty=oneline
當 oneline 或 format 與另外一個 log
選項 --graph
結合使用時尤爲有用。 這個選項添加了一些ASCII字符串來形象地展現你的分支、合併歷史:
$ git log --graph
$ git log -- documents/test
$ git log -S "git"
cherry-pick容許咱們提取一個或多個現有的提交,並使用這些提交的快照來建立新的提交。這個功能在處理生產bug時將會很是有用。
$ git cherry-pick 3016bb0b1a3deede145d5f93773ffc7928f22e73 [master 4aff2cc] experiment Date: Mon Apr 16 10:48:55 2018 +0800 2 files changed, 3 insertions(+), 1 deletion(-)
因爲使用cherry-pick建立的提交標識名都是一致的,因此兩個應用了同一提交的分支在合併時並不會產生衝突,git會完美的將他處理成一次提交。
將HEAD指針和當前分支指針回退一個提交版本。
一個「^」符號表明回退一個版本,三個就回退三個版本。
$ git reset HEAD^
咱們能夠制定回退到某一次提交
$ git reset 3016bb0
此命令用於查看操做日誌。git全部的操做在這裏都能找到。
$ git reflog 3016bb0 (HEAD -> bug) HEAD@{0}: reset: moving to 3016bb0 5e96789 HEAD@{1}: reset: moving to HEAD^ 3016bb0 (HEAD -> bug) HEAD@{2}: reset: moving to 3016bb0 3016bb0 (HEAD -> bug) HEAD@{3}: reset: moving to HEAD^ b5b1cff HEAD@{4}: checkout: moving from master to bug 6bef1e9 (master) HEAD@{5}: commit: experiment
若是咱們將已提交代碼進行了回退可是,發現回退錯了。這時候在 git log中是沒法找到記錄的。這是咱們就可使用reflog命令查找到那次提交記錄,而後用reset命令指定到回退前的提交編號。 以下圖: |
此命令使用了checkout其實真正的含義是,從上次提交的文件從新檢出。你須要知道 git checkout -- [file]
是一個危險的命令,這很重要。 你對那個文件作的任何修改都會消失 - 你只是拷貝了另外一個文件來覆蓋它。 除非你確實清楚不想要那個文件了,不然不要使用這個命令。
$ git checkout -- README.md
撤銷全部工做區修改
$ git checkout -- .
文件從暫存區撤銷到工做區
$ git reset HEAD README.md Unstaged changes after reset: M README.md
撤銷全部暫存區修改
$ git reset HEAD .
有時候咱們提交完了才發現漏掉了幾個文件沒有添加,或者提交信息寫錯了。 此時,能夠運行帶有 --amend
選項的提交命令嘗試從新提交
$ git commit --amend
這個命令會將暫存區中的文件提交。 若是自上次提交以來你還未作任何修改(例如,在上次提交後立刻執行了此命令),那麼快照會保持不變,而你所修改的只是提交信息。
有時,當你在項目的一部分上已經工做一段時間後,全部東西都進入了混亂的狀態,而這時你想要切換到另外一個分支作一點別的事情。 問題是,你不想僅僅由於過會兒回到這一點而爲作了一半的工做建立一次提交。 針對這個問題的答案是 git stash
命令。
儲藏會處理工做目錄的髒的狀態 - 即,修改的跟蹤文件與暫存改動 - 而後將未完成的修改保存到一個棧上,而你能夠在任什麼時候候從新應用這些改動。
須要注意的是工做區和暫存區的代碼會所有被貯藏。
git stash
git stash save "stash註釋"
$ git stash list stash@{0}: WIP on master: 5e96789 experiment stash@{1}: WIP on master: 5e96789 experiment stash@{2}: On bug: Uncommitted changes before rebase
若是想要應用其中一個更舊的儲藏,能夠經過名字指定它,像這樣:git stash apply stash@{2}
。 若是不指定一個儲藏,Git 認爲指定的是最近的儲藏
恢復的時候若是不加參數將會將儲藏得全部內容恢復到工做區,若是增長了--index參數則會分別恢復到紅做區和暫存區。
$ git stash apply stash@{2}
就像apply同樣將內容恢復,可是回覆後的內容將從儲藏區刪除。
$ git stash pop stash@{2}
將儲藏區全部內容所有清空,一旦清空這些代碼將永久丟失。因此要當心。
$ git stash clear
$ git stash drop <stash@{id}>
若是想查看你已經配置的遠程倉庫服務器,能夠運行 git remote
命令。 它會列出你指定的每個遠程服務器的簡寫。 若是你已經克隆了本身的倉庫,那麼至少應該能看到 origin - 這是 Git 給你克隆的倉庫服務器的默認名字
$ git remote origin
你也能夠指定選項 -v
,會顯示須要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL。
$ git remote -v origin ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (fetch) origin ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (push)
建立一個新的遠程倉庫
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote rename origin origin1
git remote rm origin1
這個命令會訪問遠程倉庫,從中拉取全部你尚未的數據。 執行完成後,你將會擁有那個遠程倉庫中全部分支的引用,能夠隨時合併或查看。
必須注意 git fetch
命令會將數據拉取到你的本地倉庫 - 它並不會自動合併或修改你當前的工做。 當準備好時你必須手動將其合併入你的工做。
$ git fetch
此命令是倉庫級別的,fatch會將全部分支的變動都拉下來。
指定拉取代碼的倉庫名稱
$ git fetch origin
從遠程倉庫拉取變動並自動合併當前分支。pull命令會先執行fetch命令將遠程倉庫的變動拉取到本地,而後嘗試將當前分支與對應的跟蹤分支進行merge合併。
$ git pull
這裏注意fatch是倉庫級別的而pull是分支級別的。
當咱們但願拉取分支後執行的不是merge而是rebase時咱們可使用此命令
git pull --rebase
咱們也能夠修改配置文件讓pull默認執行rebase
git config --global pull.rebase true
拉取後與指定分支進行合併
$ git pull origin dev_5.3
當你想分享你的項目時,必須將其推送到遠程分支。此命令將當前分支推送至跟蹤的遠程分支。
git push
這裏注意fatch是倉庫級別的而push是分支級別的。
當前分支推送到指定的分支
git push origin master
當本地分支與遠程分支不一樣名時使用此命令
git push origin mymaster:master
將本地建立的分支推送到遠程倉庫
git push -u origin <branch name>
-u 表示添加本地分支與遠程分支的跟蹤分支。
咱們也能夠建立與本地分支不一樣名的遠程分支
git push -u origin mymaster:master
git push origin --delete serverfix
將一個空分支推送給遠程分支實現刪除操做。
git push origin :master
這個命令以字母順序列出標籤;可是它們出現的順序並不重要。
$ git tag
$ git tag -n
你也可使用特定的模式查找標籤。 例如,Git 自身的源代碼倉庫包含標籤的數量超過 500 個。 若是隻對 1.8.5 系列感興趣,能夠運行:
$ git tag -l 'v1.8.5*'
一個輕量標籤很像一個不會改變的分支 - 它只是一個特定提交的引用。與svn不一樣git的標籤是不能夠移動的。
$ git tag v6.0
附註標籤是存儲在 Git 數據庫中的一個完整對象。 它們是能夠被校驗的;其中包含打標籤者的名字、電子郵件地址、日期時間;還有一個標籤信息;而且可使用 GNU Privacy Guard (GPG)簽名與驗證。
$ git tag -a v1.4 -m 'my version 1.4'
你也能夠對過去的提交打標籤。
$ git tag -a v1.2 9fceb02
$ git tag -d v6.0 Deleted tag 'v6.0' (was e26bdca)
$ git push origin v5.5
$ git push origin --tags
將一個空標籤推送給遠程分支實現刪除操做。
git push origin :v1.0.0
git checkout -b master v6.0
$ git branch dev_5.2 * master
建立分支時會在當前所在的提交對象上建立一個指針。
建立分支時很容易被理解成從當前分支建立一個分支,其實git並無考慮分支之間的關係。只不過當前分支也湊巧指向了當前所在的提交,因此只是建立了指向當前提交的指針與其它分支無關。
git branch -d hotfix
$ git branch -v * bug1 fe13e9b 生產環境修改一個bug dev_5.2 fe13e9b [ahead 5] 生產環境修改一個bug master fe13e9b [ahead 5] 生產環境修改一個bug
從遠程分支建立的本地分支,都會自動建立一個跟蹤分支來維護本地分支與遠程分支的對應關係。
咱們在pull或push代碼時就會與對應的遠程分支進行交互。
$ git branch -vv * bug1 fe13e9b 生產環境修改一個bug dev_5.2 fe13e9b [origin/dev_5.2: ahead 5] 生產環境修改一個bug master fe13e9b [origin/master: ahead 5] 生產環境修改一個bug
這會將全部的本地分支列出來而且包含更多的信息,如每個分支正在跟蹤哪一個遠程分支與本地分支是不是領先、落後或是都有。
咱們想本身指定本地分支的遠程跟蹤分支時使用此命令
$ git branch --set-upstream-to=origin/dev_5.2 Branch bug1 set up to track remote branch dev_5.2 from origin.
$ git branch -a * bug1 dev_5.2 master remotes/origin/HEAD -> origin/master remotes/origin/dev_5.2 remotes/origin/master
$ git branch --merged
$ git branch --no-merged
Git有一個名爲HEAD的特殊指針,指向當前所在的本地分支(譯註:將 HEAD
想象爲當前分支的別名)。
切換分支就是將HEAD指針指向目標分支而已。
git checkout testing
分支切換會改變你工做目錄中的文件 在切換分支時,必定要注意你工做目錄裏的文件會被改變。 若是是切換到一個較舊的分支,你的工做目錄會恢復到該分支最後一次提交時的樣子。 若是 Git 不能幹淨利落地完成這個任務,它將禁止切換分支。 |
想要新建一個分支並同時切換到那個分支上,你能夠運行一個帶有 -b
參數的 git checkout
命令
$ git checkout -b bug1 Switched to a new branch 'bug1'
$ git checkout -b master1 origin/master Switched to a new branch 'master1' Branch master1 set up to track remote branch master from origin.
咱們想將出現分叉提交的分支整合在一塊兒時,可使用合併(merge)操做來完成。
Git 會使用兩個分支的末端所指的快照以及這兩個分支的工做祖先,作一個簡單的三方合併。
$ git merge hotfix
快進合併(fast-forward) 當你試圖合併兩個分支時,若是順着一個分支走下去可以到達另外一個分支,那麼 Git 在合併二者的時候,只會簡單的將指針向前推動(指針右移),由於這種狀況下的合併操做沒有須要解決的分歧——這就叫作 「快進(fast-forward)」。 master只要向前推動就能夠完成與iss53的合併,因此會使用快進合併。 |
有時候合併操做不會如此順利。 若是你在兩個不一樣的分支中,對同一個文件的同一個部分進行了不一樣的修改,Git 就無法乾淨的合併它們。在合併它們的時候就會產生合併衝突。
解決衝突步驟:
一、須要手動解決衝突並標記已解決。
$ git add README.md
二、須要本身提交新的合併提交。
$ git commit
你能夠提取在一個分支中引入的補丁和修改,而後在另外一個分支的基礎上應用一次。 在 Git 中,這種操做就叫作 變基。
Git變基時咱們要分清,那個分支產生了補丁,那個分支是基底分支。
$ git rebase master First, rewinding head to replay your work on top of it... Applying: experiment
上例的當前分支(experiment)爲補丁分支,rebase後面跟基底分支(master)。也就是說用experiment分支的提交建立補丁,在master分支上從新執行一遍。
從上圖能夠看出,分叉提交C4不見了,在C3後面從新提交了C4'。master基底分支指針不移動,experiment補丁分支指針指向C4'。
最後若是咱們想要讓master分支指針也指向最新提交C4',咱們能夠切換到master分支執行快進合併(fast-forward)。
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git merge experiment Updating 4f3f69a..373256b Fast-forward README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
咱們能夠指定補丁分支變基到基底分支上。
$ git rebase master experiment First, rewinding head to replay your work on top of it... Applying: experiment
還有一種更加複雜的用法。從master分支建立server分支,從server分支建立client分支。
若是咱們想將client相對於server的不一樣提交變基到,master上咱們能夠這樣使用。
$ git rebase --onto master server client
在變基時若是發現補丁分支快照與基底分支快照存在衝突,變基會中止而且要求手動解決衝突。
變基中止時咱們可使用--continue | --abort | --skip參數來控制變基行爲。
$ git rebase --continue
處理完衝突後使用此命令繼續變基
$ git rebase --abort
放棄本次變基,還原成變基以前的樣子
$ git rebase --skip
放棄補丁版本快照,繼續使用基底版本快照。
交互式變基使用屢次提交,從新創建提交。提交重建範圍爲沒有push到遠程分支的提交。
$git rebase -i
如今咱們要對每次提交設置命令。通常的合併咱們會將第一次提交選擇爲pick然後面的提交選擇爲squash。這樣就會用全部的提交生成一次新的提交。
pick 4f3f69a experiment pick 373256b experiment pick 3258dad experiment pick 167f684 experiment pick cd871a6 experiment pick d06c0a0 experiment pick 9f3e252 experiment # Rebase 1221f68..9f3e252 onto 1221f68 (12 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
而後系統提示從新編輯提交說明。(被合併的提交說明會默認按順序添加)
最後咱們使用git log查看提交日誌發現已經剩下一次提交了。
咱們在進行交互式變基的時候能夠指定變基提交的次數。HEAD參數後面每增長一個「^」符號表明向後提取一次分支。
$ git rebase -i HEAD^^^^^
這個命令表明從當前提交向後獲取5次提交進行交互式變基。