官方文檔: https://git-scm.com/doc推薦看看這本介紹 Git 的電子書,看完什麼都知道了,介紹的很詳細
Git電子書下載 【PDF】 【EPUB】 【MOBI】javascript
Git是如今流行的VCS
(「Centralized Version Control Systems」 版本控制系統)之一。版本控制系統主要目的是,控制項目不一樣版本,可隨時回溯到任何須要的版本。
如軟件開發行業,版本控制系統扮演着不可或缺的重要角色。
VCS
能夠把軟件開發的各個崗位鏈接起來,各自完成本身的工做,且層次分明,前端和後臺的工做同時進行。VCS
能夠把全部管理的文件都進行版本標記,若是任何文件修改出錯,均可以隨時恢復到前面的任何版本。
說白了,VCS
能夠把開發人員緊密聯合起來,你們同時進行開發,不會出現先後端融合錯誤。
使用 git 每一個用戶都會在本地擁有 git 倉庫的全部信息,過往記錄,因此能夠隨時隨地的提交代碼。html
git 對文件版本的記錄區別於其它 vcs, 其它vcs是對每一個版本的文件進行標記,而 git 是對每一個版本的全部文件進行快照,並根據項目內的全部文件計算出 hash 值來記錄版本號。保證完整性。前端
來欣賞一下 Bootstrap 的部分提交記錄和目前的分支狀況java
你的文件可能處於尺寸三種狀態之一:已提交(committed)、已修改(modified)和已暫存(staged)
由此引入 Git 項目的三個工做區域的概念:Git 倉庫、工做目錄以、暫存區域。git
基本的 Git 工做流程以下:github
windows
的我就不說了,須要的請自行百度。
Mac 系統在安裝 Xcode 的時候就會自動安裝
查看當前版本正則表達式
git --version # git version 2.17.2 (Apple Git-113)
git 自帶 git config
工具來修改 git 的配置文件shell
/etc/gitconfig
系統上每個用戶及他們倉庫的通用配置,帶 --system
參數使用 git config
時,會讀寫這個文件 ~/.gitconfig
是隻針對當前用戶。 帶 --global
參數可讀寫此文件.git/config
每個級別覆蓋上一級別的配置,因此 .git/config 的配置變量會覆蓋 /etc/gitconfig 中的配置變量。vim
安裝完git,第一件事就是設置用戶名和郵件地址,這些信息會在每次提交時使用windows
$ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com
默認的編輯器是 vim,若是你想自定義編輯器,能夠經過這個指令指定:
$ git config --global core.editor 編輯器名稱
git config --list
能夠查看你的 git 配置信息
$ git config --list user.name=John Doe user.email=johndoe@example.com ...
git init
這個命令會將本目錄初始化爲一個代碼倉庫,並在目錄中增長 .git 目錄,裏面是關於本倉庫的全部信息。
初始化以後,目錄中的文件並無加入到 git 的版本控制中,須要手動將文件添加到 git 的控制列表中,操做見下一步。
$ git add *.c $ git add LICENSE $ git commit -m 'initial project version
在 git 管理的目錄下 新建文件 .gitignore
如:
*.[oa] *~
上面的文件意思是忽略全部以 .o
.a
的文件,忽略以 ~
結尾的文件
.gitignore
的格式規範:
#
開頭的行會被忽略/
開頭防止遞歸/
結尾指定目錄!
反向選擇glob shell 所使用的簡化了的正則表達式
*
0個或任意個字符[abc]
任意其中一個字符?
匹配一個字符[0-9]
表示匹配任意中間的字符**
兩個星表示任意中間目錄a/**/c
a/b/c
a/d/c
git status
查看當前目錄下的文件狀態,若是有文件未加入到跟蹤中,會提示你。
git status -s
能夠查看簡短的報告
git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
??
表示未跟蹤的文件A
表示新添加的文件MM
右邊的M表示修改後未保存到暫存區,左邊表示修改並放入了暫存區
若是咱們新建了一個名爲 README
的文件,git status
會顯示文件沒有被跟蹤,經過如下指令把文件添加到 git 的文件跟蹤中。
加入到跟蹤中後,沒有 commit
以前,文件處於暫存區。
git add README
若是這時候修改了 README
文件,再用 git status
查看狀態的時候,會看到提示 changes not staged for commit
,此時若是想在下次 commit
的時候提交此次修改,須要再次 git add
這個文件。git add
能夠理解爲標記文件到下次提交,而非只是添加文件到跟蹤狀態
在修改了文件以後,沒有添加到暫存區以前,能夠用 git diff
查看先後版本的區別
這是在文件沒有添加到暫存區的時候的查看方式,在存入後,須要用 git diff --cached
來查看不一樣
git commit
這會打開默認的文本編輯器,讓你輸入這次提交的信息。就像平時用 vi 編輯文本那樣,按 i
進入輸入模式,而後輸入你要寫的話,再 esc
wq
保存退出就會提交了。
或者用簡短的方式,直接在命令中輸入這次提交的信息,多個 -m
參數會做爲多個分段。
git commit -m '初次提交'
若是閒每次添加文件麻煩,能夠用 -a
參數跳過添加到暫存區的操做,直接在提交的時候把全部已經跟蹤的文件上傳。
git commit -a
移除文件並取消該文件的跟蹤,須要用 git rm
指令,並刪除本地文件。
若是隻是在目錄中刪除了文件,在 git status
的時候會提示文件沒有添加到跟蹤中。
若是文件已經添加到暫存區,且修改了文件尚未提交,此時刪除文件就須要用 -f
參數了。
只移除文件跟蹤,不刪除文件
git rm -cached README
git rm
後面還能夠跟 glob 模式的匹配字符串
git mv
給文件重命名用這個指令
其實它是三個指令的集合
mv README.mb README git rm README.mb git add README
因此用 git mv
會更方便一些。
git log -p -2
-p
顯示不一樣版本的區別-2
顯示最近的再次更新
--stat
能夠查看每次更新的簡略信息--graph
以字符圖的樣子顯示分支狀況
有時候,在提交了以後發現有幾個文件沒有提交,能夠用 git commit --amend
。
git commit -m "initial commit" git add forgotten_file git commit --amend
若是在你提交以後,在沒有修改文件以前立刻添加未提交的文件,再 --amend
就會打開上次提交的註釋,接着編輯信息,而後再提交。
查看當前目錄下的遠程倉庫 URL
git remote
git remote -v
$ git remote -v diary git@github.com:KyleBing/Diary.git (fetch) diary git@github.com:KyleBing/Diary.git (push)
在URL前面若是顯示 origin
那是 git 給 URL 倉庫的默認名字,
git remote add tb git@github.com:KyleBing/TouchbarBBT.git
這樣就添加了 git@github.com:KyleBing/TouchbarBBT.git
的倉庫,別名爲 tb
這時候拉取遠程倉庫內容的時候,直接用 tb
代替 git@github.com:KyleBing/TouchbarBBT.git
git fetch [倉庫別名]
這個指令會拉取遠程倉庫的全部內容,包括全部分支。
git pull
會拉取遠程分支到當前分支,並自動合併。
git push [倉庫別名] [分支名]
會將你的項目推送到遠程
git remote show [倉庫別名]
在沒有設置倉庫別名的時候,git 會默認把這個倉庫命名爲 origin
$ git remote show tb * remote tb Fetch URL: git@github.com:KyleBing/TouchbarBBT.git Push URL: git@github.com:KyleBing/TouchbarBBT.git HEAD branch: master Remote branch: master tracked Local ref configured for 'git push': master pushes to master (local out of date)
git remote rename origin tb
重命名 origin
爲 tb
git remote rm tb
移除遠程倉庫 tb
git tag
列出已有標籤
git tag -l 'v1.8.5'
只查看 v1.8.5 的相關版本
v1.8.5 v1.8.5-rc ...
添加 annotated 標籤,用 -a
參數
git tag -a v1.4 -m "tag version info"
git show v1.4
能夠查看標籤和對應的提交信息
git tag -v1.4 -lw
不須要填寫提交信息
查看過往提交記錄,而後取一個記錄的校驗和的部分字符串,把該提交打成標籤
git log --pretty=online # 顯示爲 86bc9a426f04817fe47c07685ac60e0fcdd33af9 (HEAD -> master, tb/master) 添加外部連接 4200265a6990c78fb5d0667eb0bbb99ab2760fc0 Merge branch 'master' of github.com:KyleBing/TouchbarBBT 6df11cb1ee1726291d8ef20da1a93773a8e40fff Last 6529785f35f5f2fd6333d95430d46e6dc75c590f Update README.md aa6a05ba99933e5505969d36f66191a499e7c2b8 文章發佈前的版本 7eaa5924d0b5e7675d90d9b31b8daedaacaca0ea 定稿 4f2320c2dcbe5ccd9dac551817cbc90653fd377b 調整按鈕尺寸大小,正在播放背景色改成黑色 18dce9bf2c84183e9030d5f7e8431ca2c0504a57 Update README.md af58e9c024ecbe2994d0c3bb21ab112dbed008fa 更新說明文檔 04da2e77f336f87827e2cf5801305f075c45d7dd 添加默認 touchbar 文件,添加 最新 Touchbar 文件 d797ff57fd5ff74c233c804fb627c7df04456595 Update README.md d8a1f7ea817a0aa51ff5b2c1f075e064a9a323f7 Merge branch 'master' of github.com:KyleBing/TouchbarBBT f9075467294865fe1a31b0879aa2d11071fe1110 修改目錄名字,添加實際照片 51fde532cb2d1ef7197d14e66cdaaed46dc8be3a Create README.md d0611a4e511641e772e56ec7c923291e254a54ad 初始化該倉庫,添加基礎的配置文件和基礎的圖標
git tag -a v1.2 51fde
git push
並不會把標籤傳送到遠程倉庫,顯式的推送纔會顯示。
git push origin v1.3
用 --tags
會把全部不在遠程服務器的標籤都推送到服務器上
git push origin --tags
刪除本地標籤
git tag -d v1.3
git checkout 2.0
git 能夠像系統那樣設置別名
git config --global alias.co checkout git config --global alias.br branch git config --global alias.ci commit
git ci -m "infos" # 跟下面做用同樣 git commit -m "infos"
若是項目中新建了三個文件,在提交的時候,Git 倉庫中有五個對象:
git 的分支,實際上是指向不一樣提交版本的指針。在 git init
初始化的時候,默認生成了一個名爲 master
的分支,其實它跟其它分支的等級是同樣的,都只是一個分支,默認名爲 master
,只是咱們都懶得給它更名罷了。
git 還有一個名爲 HEAD
的指針,做用是指向當前本地庫正在的修改的分支,如上圖,本地庫正在 master
分支上作修改。
git branch testing
上面的指令的結果如上圖,在當前版本上新建了一個名爲 testing
的分支。
git branch
只是建立一個分支,並不會切換到該分支。
git checkout testing
上述操做會把 HEAD
指針指向 testing
分支,做用以下圖:
當前在 testing
分支上,如今新建並提交一個文件,只會保存在 testing
分支上,而 master
分支還停留在前一個提交狀態上,也就是說該文件只存在於 testing
分支上。
效果以下圖;master
沒有動,testing
已經向前移動到了最新的節點。
切換分支的時候會改變本地的目錄結構
切換分支的時候,本地文件會變到當前分支的目錄結構上,若是因爲特殊緣由無法切換分支的時候,會提示切換分支失敗。
此時咱們再切換回 master
分支並作修改後提交,master
指針就會指向新的提交節點。此時,master
testing
分別處於不一樣的提交節點上,以下圖:
git log --online --graph --all
terminal 界面效果如圖:
工做中的常見情景:
正常開發過程當中,若是出現了一個嚴重問題,須要緊急修補,能夠這麼作:
若是項目已經有了必定的提交記錄,當前狀態是下面這樣:
爲了修復一個問題編號是 #53
的問題,須要新建一個分支並在這個分支上開始修復工做
git checkout -b iss53 # 上面的命令是下面兩條指令的簡寫 git branch iss53 git checkout iss53
你已經在分支 iss53
上作了必定的修改並提交了,此時的倉庫是這樣的:
此時,公司又有問題須要修改,沒必要把 iss53
和新問題混在一塊兒修改,直接在原有 master
分支上新建一個分支並在其上面修改便可。
# 切換到 master 分支 git checkout master # 建立新問題分支 hotfix git checkout -b hotfix
此時的倉庫狀態:
這樣,你能夠在任意分支之間切換,且不會影響主分支 master
的正常運行。
假如,如今已經解決了主線上的問題,須要把 hotfix
分支合併到主線上。須要先切換到主分支 master
上,而後執行合併 hostfix
的操做
# 切到 master 分支 git checkout master # 合併 hotfix 分支 git merge hotfix # 結果 Updating f42c576..3a0874c Fast-forward index.html | 2 ++ 1 file changed, 2 insertions(+)
能夠看到反饋信息中的 fast-forward
提示,這是由於 hotfix
是在 master
分支新建的,並在其基礎上作的修改,他們的合併操做只須要 HEAD
指針執行簡單的前移便可,如圖:
hotfix
問題解決併合併到主分支以後,你要回到以前的 iss53
分支繼續解決 #53 問題。在切回去以前,你應該先已合併的 hotfix
分支刪除,由於合併以後 master
和 hotfix
指向了同一個位置,已經不須要 hotfix
了,執行操做:
# 刪除 hotfix 分支 git branch -d hotfix
倉庫如今是這樣的:
通過奮力修改後,解決了 #53 問題,須要把 iss53
合併到 master
主分支中
# 切換到 master 主分支 git checkout master # 合併 iss53 分支到 master git merge iss53 # 結果 Merge made by the 'recursive' strategy. index.html | 1 + 1 file changed, 1 insertion(+)
此次 merge 跟以前 hotfix
分支的合併並不同。這是由於,master 分支所在提交併非 iss53
分支所在提交的直接祖先,此時須要比對 master
iss53
和 他們相交的 C2
進行合併:
上面的合併後,倉庫是這樣的:
合併後須要刪除無用的分支
git branch -d iss53
若是前面提到的 iss53
hotfix
兩個分支都修改了同一個文件的同一個地方,那麼在合併的時候,git自動合併就會失敗,須要手動解決衝突:
# 合併 iss53 git merge iss53 # 結果 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result.
此時查看狀態會顯示有一個文件未合併(unmerged)
# 查看倉庫當前狀態 git status # 結果 On branch master You have unmerged paths. (fix conflicts and run "git commit") Unmerged paths: (use "git add <file>..." to mark resolution) both modified: index.html no changes added to commit (use "git add" and/or "git commit -a")
出現衝突的時候,git 會在衝突文件中添加標準的衝突標記符,像下面這樣子:
HEAD
所指示的版本在這個區段的上半部分(======= 的上半部分),而 iss53
分支所指示的版本在 ======= 的下半部分。 爲了解決衝突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也能夠自行合併這些內容。 例如,你能夠經過把這段內容換成下面的樣子來解決衝突:
<div id="footer"> please contact us at email.support@github.com </div>
解決衝突以後,用 git add
添加衝突文件到暫存區,此時 git 會認爲衝突已經解決,並移除衝突標記。
也能夠用圖形化的工具來解決衝突 git mergetool
會啓動合適的合併工具,其幫助信息以下:
git mergetool This message is displayed because 'merge.tool' is not configured. See 'git mergetool --tool-help' or 'git help config' for more details. # 這裏顯示支持的工具列表 'git mergetool' will now attempt to use one of the following tools: opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge Merging: index.html Normal merge conflict for 'index.html': {local}: modified file {remote}: modified file Hit return to start merge resolution tool (opendiff):
此時查看狀態:
# 查看狀態 git status # 結果 On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: index.html
完成提交:
# 執行提交 git commit # 結果 「Merge branch 'iss53' Conflicts: index.html # # It looks like you may be committing a merge. # If this is not correct, please remove the file # .git/MERGE_HEAD # and try again. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: index.html #
git branch 命令不僅是建立和刪除分支,不加參數時會列出全部分支
# 查看分支列表 git branch # 結果 iss53 * master testing
*
表示當前 HEAD
指針的指向,也就是當前所處的分支。
查看每一個分支的最後一次提交:
# 查看分支最後提交 git branch -v # 結果 iss53 93b412c fix javascript issue * master 7a98805 Merge branch 'iss53' testing 782fd34 add scott to the author list in the readmes
---gerged
--no-merged
用於查看已合併的和未合併的分支
git branck --merged # 結果 iss53 * master
能夠看到當前 iss53
已合併到 master
中,能夠刪除 iss53
分支了。
當分支沒有合併時,執行刪除分支操做會失敗:
git branch -d testing # 結果 error: The branch 'testing' is not fully merged. If you are sure you want to delete it, run 'git branch -D testing'.