版本控制就是記錄項目文件的歷史變化。它爲咱們查閱日誌,回退,協做等方面提供了有力的幫助。java
版本控制通常分爲集中化版本控制和分佈式版本控制。git
集中化主要的版本數據都保存服務端。github
分佈式版本數據分散在多端。算法
Git屬於分佈式版本控制,也是如今比較流行的一種版本管理工具。shell
Git項目有三個區塊:工做區 / 暫存區 / 版本庫vim
Git工做流程windows
# 下載 <<==== clone # 上傳 ====>> add ====>> commit ====>> push # 更新 <<==== merge|rebase <<===== fetch
咱們將一個更新操做拆分爲數據更新+合併處理兩部分,這樣來看 fetch 只是進行數據更新。而pull 實際上是 ( fetch + (merge|rebase) )組合操做,它執行數據更新同時執行合併處理。pull 默認是fetch+merge 組合 ,也能夠經過參數 --rebase 指定爲 fetch + rebase。bash
合併處理是Git很重要的一塊知識。兩個命令在工做中也常常使用,區分它們對咱們頗有用。ssh
場景以下編輯器
項目有一個mywork分支。C2時間點我和小明各自下載項目進行功能開發,小明效率比較高,先推送了C3 C4 到遠程倉庫。我本地倉庫如今有C5 C6兩個提交,要推送到遠程倉庫,需先同步遠程倉庫版本。
若是經過 fetch + merge 方式,Git會將遠程最新(C4)和本地最新(C6)進行合併併產生一個新的(C7)。
衝突處理步驟
git merge # 發生衝突會出現衝突標記 「<<<<<<< HEAD 40 ======= 41 >>>>>>> 41」 # 手動處理衝突 git add . git commit -m 'fix conflict' git push origin HEAD
若是經過 fetch + rebase 方式,git會先將C5 C6存儲到.git/rebase零時目錄,合併成功後刪除。
衝突處理步驟
git rebase # 發生衝突會出現衝突標記 「<<<<<<< HEAD 40 ======= 41 >>>>>>> 41」 # 手動處理衝突 git add . git rebase --continue git push origin HEAD
git merge 會產生大量Merge日誌,可能會對查看帶來不便。不過你們仍是根據實際狀況進行選取。
提交後發現有文件漏了,又不想提交兩次。此時經過 「git commit --amend」 能夠合併爲一個提交。
git commit -m 'initial commit' git add .gitignore git commit --amend
若是文件想撤回且還沒有提交,執行下面命令撤出暫存空間(index)
git reset HEAD <file>...
關於 reset 其它用法
# 重置到指定版本,以前提交內容將丟失 git reset --hard HEAD # 重置到指定版本,保留更改的文件但未標記爲提交 git reset --mixed HEAD # 重置到指定版本,保留全部改動文件 git reset –soft HEAD
特別注意 當你使用 「git reset --hard HEAD」 重置到某一版本,發現搞錯了想回退。這時你可能會執行「git log」,可是發現已經沒有之前的版本記錄,怎麼辦?送你一瓶後悔藥以下
# reflog 是Git操做的全日誌記錄 git reflog 6241462 (HEAD -> master) HEAD@{0}: reset: moving to 6241462 ea9b5ab HEAD@{1}: reset: moving to ea9b5ab 6241462 (HEAD -> master) HEAD@{2}: commit: Hello 34cd1e3 HEAD@{3}: commit: 3 ea9b5ab HEAD@{4}: commit: 2 729a8b1 (origin/master) HEAD@{5}: commit (initial): 1 # 找到最左邊對應hash值就能夠回退到任意位置 git reset --hard {index}
若是想撤回文件修改內容且文件還沒有提交,執行下面命令
git checkout -- <file>
若是建立的分支名稱須要更改
git branch -m old new # 若是分支已經推送到遠程,先刪除再推送新分支 git push origin --delete old git push origin new
若是須要撤回的提交已經推送到了遠程倉庫,那麼補救的方式只有建立新的提交。
能夠利用revert快速撤回到須要回退的版本。
# 還原最近一個提交 git revert HEAD # 還原倒數第二個 git revert HEAD^ # 還原倒數第第四個 git revert HEAD~3
這一節介紹一下Git版本庫的存儲模型。
項目歷史變更信息都記錄在object文件。文件名稱是經過哈希算法 ( 這裏是SHA1(對象內容) ) 產生的40位字符。
這種作法的一個優勢就是「在對比兩對象是否相同時,只須要比較文件名稱就能迅速得出結果」
哈希算法:簡單來講就是向函數輸入一些內容,輸出長度固定的字符串。這裏SHA1函數固定輸出40長度字符。
object文件分 blob tree commit tag 四種類型
特別注意:Subversion,CVS,Perforce,Mercurial等是存儲先後兩次提交的差別數據。Gi-每次提交時,它都會以樹狀結構存儲項目中全部文件的外觀快照。
Blob 是二進制數據塊,不會引用其它東西。若是目錄樹(或存儲庫中多個不一樣版本)中的兩個文件具備內容相同,它們將共享相同的Blob對象。
Tree 存儲blob和tree的引用。
# 我查詢 add1a1306e20... git ls-tree add1a1306e20... 100644 blob 4661b39c3460a5c1f9e9309e6341962e0499b037 README.md 040000 tree ad46b24a4b0648ede3ca090dde32c89b89f7f2c1 src ...
Commit 包含下面幾個信息
git show -s --pretty=raw add1a1306e.... commit add1a1306e.... tree 81d4e4271a56575da7f992dc0dfc72ff7ddff94c parent cd397e4c373013b19825b857b43ad8f677607f5d author lixingping <lixingping233@gmail.com> 1589783810 +0800 committer lixingping <lixingping233@gmail.com> 1589783810 +0800
git cat-file tag v_1.0 object 24d16acd6aa08f74556c7ce551fa571b4bfe4079 type commit tag v_1.0 tagger lixingping <lixingping233@gmail.com> 1588591122 +0800
假設項目目錄結構以下,咱們進行一個初始提交。幾種文件關係以下圖
|-- read.txt --| lib --| hello.java
生成SSH key
ssh-keygen -t rsa -b 4096 -C "email@example.com" # 指定生成的文件 ssh-keygen -t rsa -b 4096 -C "email@example.com" -f ~/.ssh/id_rsa_example # id_rsa_example.pub 粘貼遠程倉庫 # 配置多個遠程倉庫 touch ~/.ssh/config #添加一下內容 Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa_github Host example.com HostName example.com User git IdentityFile ~/.ssh/id_rsa_example
配置
git config –global user.name 「xxx」 git config –global user.email 「xxx@email.com「 git config --global core.autocrlf true # 建議配置 windows mac換行符不統一問題 git config --global core.editor vim # 配置默認編輯器 git config --global core.excludesfile ~/.gitignore_global # 配置全局忽略文件 git config –list # 查看配置信息
分支管理
git branch --list # 羅列本地全部分支 git branch --all # 羅列本地和遠程全部分支 git branch -r # 羅列遠程全部分支 git branch -v # 顯示各分支最後提交信息 git checkout <branch name> # 切換分支 git checkout -b <new branch name> # 建立新分支 git push origin <new branch name> # 推送新分支到遠程 git checkout -m <old branch> <new branch> # 重命名分支名稱 git branch -d <[list]branch name> # 刪除本地分支 git push origin --delete <branch name> # 刪除遠程分支
標籤管理
git tag -l # 羅列本地全部標籤 git show <tag name> # 顯示指定標籤 git tag -a v_1.0.0 -m "備註" # 建立標籤 git push origin <tag name> # 推送標籤到遠程 git tag -d <tag name> # 刪除本地標籤 git push --delete origin <tag name> # 刪除遠程標籤
工做多年以來一直在使用Git,可是對Git沒有一個系統瞭解,因此寫這篇文章歸整一下。
歡迎你們留言交流,一塊兒學習分享!!!