目錄git
什麼是github,github能作什麼?它是一個代碼倉庫,可是你能夠把它當作一個遠程硬盤(雲盤、網盤)。和通常網盤的區別在於,它經過一個叫作git的軟件進行同步,上傳或下載操做,這個軟件有很是強大的同步功能,甚至能夠創建不一樣的存儲分支,讓同步的文件有多個不一樣的版本(這對代碼開發來講是頗有意義的)。可是,若是你不想要,不須要這個功能,也能夠把它當作純粹的免費網盤使用。github
如今就有不少人,經過github來存放我的筆記,日記,博客等文檔資料,在不一樣電腦上,只要同步一下,就能繼續編輯,很是方便。這個甚至比通常的網盤要來得輕鬆,由於git對版本的控制更好,數據傳輸量更少。同步更加智能化,版本管理更加方便。安全
多說無益,本文介紹git的原理和使用方法,你親自看一下是否對你有用。bash
git是一個分佈式同步工具,簡單來講,它不要求你創建一個特定的服務器,你能夠在任何地方創建本身的存儲倉庫,不一樣的倉庫沒有地位的差別,都是平等的,這就去中心化了,因此叫分佈式。服務器
這有什麼好處,好比你不須要依賴某個網盤提供商,若是它不當心倒閉了,只要你把倉庫搬到另外一個提供商就能夠,甚至,你直接弄一臺電腦放倉庫也是能夠的。這個理念我認爲是很是有居安思危精神的。千萬別過於相信網絡,要給數據一個備份。網絡
若是是傳統的網盤,你須要用它的軟件,下載文件到你的電腦,而後用另外一家的軟件,上傳到另外一個網盤備份,不用兩天你就受不了。若是你不跟蹤備份,可能網盤沒通知你就把你的學習資料刪除了,那你是怎麼也要不回來的。相信經歷過的朋友都知道。而只需用git,就能統一的管理各個倉庫,輕鬆進行復雜的同步。編輯器
也就是儲存倉庫,可是這個倉庫不但能夠放文件,還對文件的修改、刪除等歷史記錄做跟蹤,讓你能夠回溯到某個歷史時期。這是git 最強大的功能。分佈式
爲了利用好版本管理功能,要求文件類型是文本類型,最好是UTF-8編碼的。工具
git init #在當前目錄下創建倉庫,將新建一個.git文件夾來存儲倉庫數據
在當前目錄新建文件,而後加入倉庫,git便可維護該文件的同步管理。性能
git add file.txt #將當file.txt文件加入git倉庫
添加並不會馬上提交,也不會自動同步,這個交給用戶本身判斷恰當的提交時機。
git commit -m "這裏寫備註" #提交數據
每次提交,都要求你寫一個備註,來記錄你此次提交作了什麼,這是個良好的習慣,由於這樣你回溯歷史的時候,才知道哪一個版本是你的目標版本。
當前被跟蹤的文件,和倉庫版本有什麼差別,能夠用git status
列出哪些文件改動了的文件。
若是你還想知道具體修改了什麼地方,能夠用git diff xxx
來查看xxx文件的改動狀況。
這個是比較高級的功能,也許你用得上,也許用不上。首先,git reflog
會顯示你提交文檔的版本:
#樣例輸出 f9adcba (HEAD -> master) HEAD@{0}: reset: moving to f9adc 9a75fd8 HEAD@{1}: reset: moving to HEAD~1 f9adcba (HEAD -> master) HEAD@{2}: commit: 測試回退功能 9a75fd8 HEAD@{3}: commit: 加了一點 781b0ad HEAD@{4}: commit: 有加了一點 55227c1 HEAD@{5}: commit: git文檔修改 f2d5850 HEAD@{6}: commit (amend): ss2 ff6877d HEAD@{7}: commit (initial): ss
要跳到那個版本,使用git reset --hard f9ad
,其中f9ad
用具體的版本號替換。在以上樣例的第一列,只須要給出幾位,git就會尋找到對應版本。
當跳轉到該版本,相應的文檔數據會當即修改。
當你在某個目錄下面,建立倉庫git init
,該目錄就是你的工做區,而具體的倉庫的一些配置信息,是放在.git
目錄下的(可能被隱藏)。
工做區的做用就是你要同步的文件,應該放在這個目錄下面,你只須要修改對應的文件,git負責其他的一切。你不須要刻意的去修改或者理會.git目錄下面的內容,而應該使用git軟件來輸入命令。
當用git add xxx
添加文件,實際上就是把文件放入暫存區。當git commit
就會把暫存區的內容正式提交到某個分支(之後解釋分支),並清空暫存區。
若是要撤銷工做區的修改,能夠用git checkout -- xxx
;若是要撤銷暫存區的修改,能夠用git reset HEAD xxx
。
還記的我說過git是分佈式的麼?若是隻是在本身電腦目錄建立一個倉庫,那就沒什麼意思了,如今學習怎麼添加遠端的倉庫。
首先,申請github.com網站的帳戶,並申請一個倉庫的使用權,而後獲得一個倉庫的連接地址,而後:
git remote add 倉庫別名 連接 #添加遠端倉庫 git push -u 倉庫別名 master #將本地分支master提交到倉庫。-u表示關聯對應分支 git remote -v #顯示遠程倉庫狀況 git pull #從遠程倉庫拉取最新版本
git容許創建不一樣分支,所謂的分支,就是另外一條修改文件的路線。git記錄每一條路線不一樣的修改內容,當合並的時候會要求你對有衝突的修改內容進行選擇。
git branch git #建立名爲git的分支 git checkout git #切換到git分支 git branch #查看當前分支狀況 git merge git #將git合併到當前分支 git branch -d git #刪除git分支
建立分支後,所作任何修改,隻影響當前分支,當切換分支,文件會瞬間回到另外一個分支的狀態下。
雖然git分支這個功能看上去很強大,又很複雜,但實際上運做很是高效,它總能按照你指望的方式去運做。所以,推薦多使用,用來劃分不一樣的關注點也是挺好的。
一個合理的使用分支的方法是:
這樣就算再多人一塊兒合做編輯,也能保證主分支是穩定可靠的。
不過,最好仍是不要隨便跳轉分支,由於跳轉分支容易致使當前數據丟失,而後還會致使不少不少的誤操做。(本博客就是這樣丟失了一些歷史信息,╮(╯▽╰)╭!)q
特別要注意,切換分支是一個高度危險的操做!由於它會毀掉當前工做區的狀態。切換分支以前,應該先提交當前修改內容到倉庫。可是,若是佔時沒法提交,能夠藉助儲藏功能,把當前工做區保存在一個棧表裏面。
git stash #保存並清空當前工做區修改狀態 git stash pop #回彈當前工做區上一個狀態。 git stash list #顯示儲藏棧表
標籤對應了commit 提交版本,由於這個版本號太複雜,所以用標籤名來代替,更加容易識別。也做爲一個發行版本號來使用。
git tag v0.9 #當前版本命名爲標籤v0.9 git tag #查看當前標籤 git tag -d v0.9 #刪除對應標籤 git push origin v0.9 #提交標籤到遠程倉庫
縱觀理論知識,咱們能夠得出一些結論:
有些操做是危險的:若是沒有提交到倉庫,就切換分支,當前工做內容就可能丟失,由於切換分支並不懂得自動保存當前工做區的狀態。只要是會對當前工做區產生影響的操做,都有可能影響到數據安全(若是當前工做區沒有提交,有修改狀態),好比拉取,同步,切換分支,版本跳轉,所以這些操做以前特別要注意查看當前工做區狀態,先提交,或者儲藏現場。
工做區和暫存區,都是不安全的,能夠視爲臨時數據,他們之間造成一個小型的臨時版本控制機制。工做區的內容能夠放到暫存區,暫存區的內容也可能回退到工做區。
git 官網在http://git-scm.com,下面以deepin系統爲例:
apt install git #安裝git git --version #版本號2.17
cd ~ mkdir gittest cd gittest git init #在gittest目錄下建立倉庫,當前工做區便是gittest git help #查看使用說明
非新項目,能夠從遠程倉庫克隆建立。
git clone https://github.com/Anduin2017/HSharp.git cloneProj #從已有的遠程倉庫克隆建立名爲cloneProj的本地倉庫。該遠程連接能夠在github任意一個公開項目中獲取。
git倉庫的配置信息,能夠存在三個地方:
/etc/gitconfig
~/.gitconfig
.git/config
#添加用戶名和郵箱信息,必備,由於每一次提交倉庫都要記錄當前提交人的這些信息 git config --local user.name "myname" #添加user.name的記錄爲myname,其中--local爲默認值,能夠省略 git config user.email myname@163.com #添加user.email爲myname@163.com git config --list #列出當前已經配置的內容 git config user.name #列出某項的值,即myname
若是不想某些文件被加入倉庫,能夠用.gitignore文件指定,內容例如:
#忽略.cpp文件和~符號結尾的文件 *.cpp *~
應該常用這個命令確認文件狀態。
注意: 若是你使用編輯器來編輯,要注意當前編輯狀態和當前文件狀態是不一樣的。git是針對文件而不能知道你有沒有正在編輯。若是你正在編輯,又經過git命令修改了文件,你的編輯器就會提示你原始文件已經被修改,你沒法保存等異常狀態。所以,你在使用git命令前,應該先把編輯狀態下的文件,用編輯器保存一下。
git status #查詢狀態
#建立一個新文件,並在末尾輸入內容「hello world!」 cat >>myfile.txt hello world! ^C #將該文件放入暫存區 git add myfile.txt #繼續編輯,並在末尾添加「hello.」 cat >>myfile.txt hello. ^C # 這時,就存在兩個不一樣的版本,一個是修改前放進暫存區的"hello word!"版本,一個是工做區內的「hello word!hello."版本。 git status #遇事不決,先用這個確認狀態。能夠發現同一個文件,有兩種狀態。一種是放在暫存區的,提示讓你提交;另外一種是在工做區的,提示讓你暫存變動。 git diff myfile.txt #確認一下文件內容的差異。顯示工做區和暫存區兩個同名文件的對比,若是你會看diff輸出格式,就能發現差異是添加"hello." #選擇1,放棄當前修改,返回上次暫存內容 git checkout -- myfile.txt #選擇2,確認修改,放入暫存 git add myfile.txt #git status的提示很豐富,提示上面有以上指令的使用格式 #刪除文件 #若是某個文件被刪除,這在git中也是一個特殊的修改 git rm xxx #刪除xxx,並把刪除狀況告知暫存區 git rm --staged yyy #從暫存區刪除yyy文件,但不影響工做區
暫存區的內容並不會產生一個穩定的版本,最終要正式加入倉庫,須要commit提交。
提交會要讓你輸入每次提交的備註,命令行下面的編輯器由git config core.editor
選項控制。
git commit #向本地倉庫提交暫存區的內容 git reset HEAD myfile.txt #取消暫存區內容。 git diff --staged #比較暫存區和倉庫版本的不一樣 git commit -a -m 」備註「 #把工做區的改動所有暫存起來,而後直接提交。-a參數將縮減提交的步驟。 git log -2 #觀察最近兩條提交記錄 git log --pretty="%h %an,%ar:%s" #按指定格式顯示記錄 git log --pretty=oneline --graph #顯示按分支提交結構圖 apt install gitk #安裝圖形化顯示記錄的工具
git remote -v #查看遠程倉庫列表 git remote add remotegit https://github.com/Anduin2017/HSharp.git #添加一個遠程倉庫,命名爲remotegit git fetch remotegit #下載遠程倉庫remotegit的對象和引用 git remote show remotegit #顯示遠程倉庫關聯信息 git remote rename remotegit newname #把遠程倉庫命名進行修改 git remote rm newname #刪除遠程倉庫的關聯 git clone https://github.com/Anduin2017/HSharp.git clonegit #克隆生成一個徹底同樣的本地倉庫,建立工做目錄爲clonegit
遠程倉庫上面的分支,稱爲遠程分支。
git remote -v #查看遠端倉庫狀況 git remote add gitbak file:///home/user/git #加入本地另外一處倉庫 git fetch gitbak #下載倉庫信息 git branch -av #查看全部分支,包括遠端倉庫 git branch --set-upstream-to=gitbak/master #當前分支關聯gitbak/master分支 git pull gitbak master --allow-unrelated-histories #合併不關聯的歷史數據 git push cloneProj HEAD:master #提交本地分支到遠端倉庫 #注意:應該儘可能保持本地分支名稱和遠程一致。
這個功能比較簡單。
git stash #儲藏當前工做區和暫存區變更 git stash pop #恢復
每一次提交,都會產生一個版本,任什麼時候候均可以跳轉到該版本,可是版本標識是一個字符串哈希序列(sha-1 40字符哈希),不方便對外公佈。
git tag #顯示現有標籤 git tag v1.0 #爲當前版本命名標籤 git show #顯示HEAD關聯提交對象信息 git show v1.0 #顯示特定版本信息 git push origin v1.0 #向遠程倉庫提交標籤 git commit -am"備註" #建立一個新提交"commit"對象,並改變HEAD指針指向新對象,若是頭指針指向某個分支,先改變該分支指向新對象,再用HEAD指針指向該分支。簡而言之,建立新版本 git reset 2341a --hard #HEAD指針調到散列爲2341a開始的commit對象,即跳到該版本,--hard參數重置當先工做區和暫存區
git中的分支,相似一個指針,一個提交(commit)相似鏈表中的一個節點。commit保存了父節點,和整個目錄樹結構,所以當分支(指針)指向某個commit,內容天然就是該節點的狀態。理解這點很重要。也許你會擔憂每次提交都產生一個當前文件目錄的快照,會不會致使存儲量變得很大,實質上是不須要擔憂的。git以一種高效的方式進行相關記錄,無論是性能仍是空間,都容許你瞬間執行提交,產生新的快照。
一開始有個master的分支,有個HEAD指針,它指向master,而master指向具體的commit節點,每次提交,master都會更新到新的節點上。若是你使用某種命令移動這個指向,天然就會變動到不一樣的版本,這就是實現版本管理的基礎。
git branch -va #顯示分支狀況,-a表示全部分支,包括遠程分支,這個命令常用,由於它會顯示分支的狀況,相似git status顯示文件狀況。 git branch testbranch #基於當前分支建立一個新分支,實質不過是複製一個指針而已,效率很是高 #當你想切換到其餘分支 #1. 保存正在編輯的文件 #2. 儲藏現場git stash push -m "備註" #2.2 或者提交git commit #3. 切換分支 #爲何?由於切換分支會清空現場,你將丟失掉工做區和暫存區的改動數據 git checkout testbranch #切換到testbranch,它和此前分支上一次提交版本如出一轍 git commit -m 「備註」 #每次提交,都會移動當前分支,指向最新的commit對象 #分支的成果最終要合併起來 git merge master #將master分支合併到當前分支 #合併過程可能會出現數據衝突,參考提示,手工選擇後合併成功 git checkout master git merge testbranch #更新master分支,通常這個分支做爲默認的主分支 git branch -d testbranch #刪除分支 #若是該分支新增的內容沒有被合併到其餘分支,就會提示讓你先合併,善用git status,根據提示來操做便可。 git mergetool #調用圖形界面來解決內容衝突
分支的功能並不算太複雜,可是如何設計適合本身須要的分支系統,就是一門值得思考的功課。建議master做爲集成主分支,有若干分支負責實際編輯,編輯完畢合併到主分支。而後每一個細分支有里程碑(用標籤標註),發佈版本應該選擇恰當的里程碑組合,進度稍微比主分支慢。
另外,若是須要修補,能夠選擇在里程碑新建一個補丁分支,它須要和主分支合併,也須要和發佈分支合併。
可能用到的技術包括:
git branch 分支名 提交對象
git checkout 分支名
git checkout xxx
git merge x1
git tag v1.0.0.f1
git checkout --detach
git reset --hard commit對象
集成merge的基本邏輯是:
所以應該採起的策略:每一個分支應該儘可能尋求共同祖先。那麼共同祖先是怎麼來的?實質之前某個merge節點(或者是分裂的初始點),不然分支怎麼會有共同祖先?所以解決集成merge衝突複雜化的辦法,實際是分紅屢次集成,也就是持續集成的意義所在。
\344\275\277\347\224\250
相似的編碼格式,能夠用:git config --global core.quotepath false