git入門手冊:git的基本安裝,本地庫管理,遠端上傳
前言:
git是分散式的版本庫控制系統,它能方便你將自己的程式碼寄存於遠端伺服器上,從而實現集體合作開發。git有GUI
圖形介面,然而使用終端命令仍是主流。以下基於Ubuntu系統操作git(其方式也適用於windows等系統),實現git的基
本安裝,關聯github賬戶,本地建立及更改庫,分支,連線遠端版本庫。
本文章講解了一般需要用到的命令,以及更重要的——git管理程式碼的機制。由於本人知識有限,若有錯誤,望
指出和諒解。
第一節 git安裝:
-
ubuntu下的安裝:
ubuntu預設沒有安裝git,alt+ctrl+t開啟終端,執行下面命令來安裝:
檢查是否安裝成功:
未報錯就代表成功安裝。
第二節 git配置設定:
以下設定只要設定一遍,以後不用重新設定
-
使用者名稱及郵箱:
-
其他配置:
啟用git輸出顯示顏色
設定git編輯器(預設為vim)
第三節 關聯github賬戶:
-
獲取ssh金鑰:
之後一路回車即可
金鑰儲存在home/.ssh/id_rsa.pub檔案裡(home目錄下.ssh是隱藏的,按快捷鍵ctrl+h顯示)
-
新增金鑰至github:
複製金鑰,開啟瀏覽器登入你的github賬戶,在setting>SSH and GPG keys 裡新增金鑰即可。
第四節 本地版本庫建立:
提示:使用git --help或者git 命令 --help
-
git三大工作區域:
1.工作目錄:即本地目錄,是可以看到的,供使用者編輯更改程式碼文件。
2.暫存區:所在目錄為.git/index,所有工作目錄中的更改要先提交到暫存區,才能讓版本庫接受。
3.版本庫:所在目錄為.git/objects。是所有程式碼的集中區域,記錄使用者提交的更改。
-
建立空的本地版本庫:
git init 命令:將普通資料夾mypro初始化為空的版本庫。
執行以上命令後會發現mypro資料夾下出現一個隱藏資料夾.git,這就是git倉庫儲存檔案的地方。
也可以刪除庫(讀者可以不刪除它,因為下面還需要一個空倉庫)
實際上就是把mypro資料夾刪掉即可
-
克隆遠端版本庫:
這是建立本地版本庫的另一種方式,也是最常用的方式,用此方法我們可以克隆他人的版本庫進行學習
和使用,我們這裡還是以自己github上的版本庫為例。
git clone +倉庫地址就可以克隆了,當然你也可以為克隆的版本庫重新命名(如果沒刪除過mypro,可以重
名為成其他名稱):
`
第五節 更新本地版本庫:
-
建立與更改檔案:
在工作目錄mypro下新建一個名為hello的文件
終端下輸入git status 檢視工作目錄的狀態:
發現有紅色的hello,說明雖然我們建立了hello文件,但屬於未跟蹤狀態,但版本庫並未記錄下這次建立.
下面,我們進行同步(正如前面所說,要將更改提交到庫,必須先提交到暫存區):
git add +檔名:提交更改到暫存區。
git commit -m "更改說明" :將暫存區的所有更改提交到庫。
當提交到暫存區後,出現“新檔案:hello”,表示更改已經被跟蹤記錄,但還未正式提交到庫,git status比較的
永遠是版本庫與工作目錄的不同。
讓我們在正式提交更改後再看一下工作區狀態:
`
因為此時版本庫與工作目錄是同步的,所以工作區狀態為無。
接下來,我們來更改hello檔案內容,新增"hello!":
請讀者自行檢視工作區狀態(在大型開發中這是非常必要的),這次顯示的是“更改:hello”,所以可以看出,git
對於更改是有明確分類的。
請讀者將更改提交到庫,註釋為“fill the context”。
-
檢視更改提交歷史:
1.git show 可以檢視最近一次更改的具體內容:
commit這一行是為更改分配的指標(專業名叫sha-1值,下文都以sha-1值稱呼),它指向這次更改。
“fill the context “是使用者新增的更改的說明。
---a/hello代表更改前的hello被代替了.
+++b/hello代表更改厚的hello,下面兩行是更改的內容,第一行可以知道被更改的行數,最後一行表示增加了
"hello!"一行。
2.git log 可以檢視歷史記錄(輸入wq後即可退出檢視):
這裡顯示我們一共更改了兩次,commit 後面是指向本次更改的sha-1值。
-
回退操作:
有時候,我們想撤銷提交,git有強大的回退操作:
1.從版本庫回退到暫存區(相當於撤銷git commit操作):
其中HEAD是一個指標,在我們回退前,它指向最後一次更改的指標(24ffa3c...讀者可在上文看到這個指標),
DAED~1 表示指標回退一個歷史點,指向上一次更改的指標(ce169e0...讀者可以使用git log檢視,可以發現ce169e0...
變成了第一個)(注意:讀者的指標同我的是不同的)。
下面請讀者輸入git commit -m "fill the context"恢復到回退前(此時會分配一個新的指標),然後在hello文件結尾加一
句“how are you”,最後提交到庫,提交說明為“change the context”,之後git log會發現有三次更改。
以上完成後,我們嘗試讓HEAD回退兩個歷史點(應該會認為結果同上面的回退是一樣的,即hello文件裡有“hello!”,hello文
檔已提交到暫存區,但未提交到庫)。
可以看到,確實回退到了建立文件之後的第一次更改,但是回退時我們的第二次更改卻沒有被刪除。
git diff --cached +sha-1值:可以對比暫存區的文件與庫中某一提交點的該文件之間的區別,這裡的sha-1值
指向建立文件的更改,那時hello文件還沒有內容。
關於如何回退時刪除第二次更改,我將在下面講到,現在讓我們提交更改到庫,操作如下:
2.回退到工作目錄:
成功回退到工作目錄,請讀者執行git checkout hello命令,放棄更改的提交。
git checkout +檔案 適用於工作目錄下更改(只能是修改不能是建立)過的,未提交到暫存區的檔案的回退。
那麼提交到暫存區的檔案如何回退到工作目錄呢?
當然是用git reset --mixed HEAD了(git reset HEAD預設是--mixed),為什麼呢?首先,--mix的作用就是回退到
工作目錄,其次HEAD後面沒跟引數,表示指向當前的sha-1值(下面例項中為68698...),下面是一個例子:
回退前:
回退後:
那麼為什麼沒有git reset --soft HEAD命令呢?因為當從庫回退到暫存狀態時,對於庫來說,放棄了這次更改,HEAD
就要指向上一次更改(e59b54...),所以這裡應該指定HEAD~1。
3.回退至上次更改:
操作前請提交三次hello的更改(請不要嫌麻煩,這至少有利於熟悉git 命令):
第一次新增“hello!”,註釋為“fill after mixedreset”;
第二次新增“how are you? ”,註釋為“change1 after mixedreset”;
第三次新增“i'm fine.”,註釋為“change2 after mixedreset”;
更改結果如下:
我們想徹底放棄第三次更改,而這次更改已經提交到庫:
我們看到狀態回退到我們第二次提交更改後的時候了。
git log --oneline:oneline引數可以簡化資訊。
現在可以回答上文提出的多歷史點回退問題:
請讀者輸入下圖中的程式碼:
上面程式碼中,我們先用hard放棄了第二次的更改,然後再用soft回退,這樣去掉了第二次更改,保留了第一次更改。
4.小結:
至此,回退操作已經講完了,需要注意的是,soft一般用於回退一個歷史點(儘管上文舉過回退兩個的例子,但很容易發現
這樣的回退是沒有意義的),適用於提交到庫的更改;--mixed 一般用於不回退歷史點或一個歷史點,分別適用於提交到庫的
更改和暫存的更改;checkout不回退歷史點,適用於未暫存的更改;--hard一般用於回退一個或多個歷史點,具有強制性與普適性。
-
拓展:
1.使用git log -g --oneline(-g引數可以列出所有分配過的sha-1值所對應的更改):
通過上圖對比(這些是我們上文操作的所有歷史記錄,讀者可以根據這些記錄回憶之前的操作,其中[email protected]{2}和[email protected]{3}是
由於本人操作失誤撤銷回退產生的,下文也會講如何撤銷回退),可以發現,不加g引數當回退的時候就會丟棄一些記錄,而加
上g引數則會顯示所有記錄(-g代表全域性,在之後的分支管理中是很重要的)。
2.使用sha-1值回退:在回退操作講解中,我們之前使用的都是HEAD~,但也可以使用sha~1值
我們用sha-1值重新實現拓展1中操作,程式碼輸入如下(這裡選擇了靜默執行):
結果如下:
第六節 分支管理:
分支無論在本地庫管理,還是大型專案集體開發,都是非常有效的管理方式。
-
本地建立刪除與切換分支:
庫在初始化後預設有一個master分支(主分支),事實上我們之前的所有操作都是在master上進行的,那麼我們可以在master分支上
衍生出一個小分支(子支),而對於這個子支來說,master就是它的父支。
下面我們就來建立兩個新的分支:
git branch 分支名:在當前分之下建立一個子支;
git checkout 分支名:切換到某分支;
git branch:檢視所有分支;
上面我們在master下建立了分支dev,dev就是master的一個副本,然後又在dev分支下建立了dev-1分支(*標註標誌當前所在分支);
請讀者在dev分支下提交hello的修改(之前回退到了暫存區),註釋為“fill at dev”:
通過上圖可以發現,由於dev是master的一個副本,當在dev下提交修改時,master並不會被影響。
再比較dev與dev-1:
這次我們用上文學過的git diff比較,發現dev-1也沒有被影響,因此可以知道,分支間在建立後就各自獨立。
我們可以刪除不想要的分支,刪除前需要切換到另一支分支,否則無法刪除(此時我們處於master,要刪除Dev-1分支):
-
分支合併:
有分必有合,我們建立分支的目的有三種:
1.利用建立的分支做一些不確定的更改,而不影響到原來的分支。
2.利用某個分支實現某個功能模組,從而利於版本管理。
3.團隊合作中,遠端庫作為根,並從根上為每個人員分配一個分支。
首先,我們將dev合併到master上(要求當前分支為master,瞭解兩個分支的更改差異):
這樣就使得master與dev同步了。
如果要取消合併,可以使用回退操作,如下:
這裡的Orig_head指上一次head所指的位置。
可以通過下面命令檢視未合併的分支(即存在更改差異的):
第七節 遠端操作:
第二節中我們已經關聯了github賬戶,一個github賬戶能夠新增多個ssh祕鑰,這樣多個人就可以提交到同一個github倉庫。
-
建立連線與推送檔案:
首先,要建立連線,並提交檔案到github:
git remote add origin 倉庫地址:加入遠端倉庫地址(並沒有連線,如果地址有錯,將不會發現),將遠端倉庫定義為origin,注意,如果
執行此命令前已經有過一個origin了,要先執行git remote remove origin刪除原來的origin。
下面就可以推送檔案了:
git push origin master:表示將本地的master同步到遠端origin的master主分支上(你可以看圖片最後一行)。
-
拉取檔案:
作為B員工,當有新的專案時,首先要做的是克隆遠端庫(git clone),而之後當遠端庫有新的檔案提交後,每個員工在提交自己的程式碼前都
應該先拉取遠端庫的檔案,使本地庫得到更新,此時不能使用git clone,而是git pull,如圖:
該比命令表示拉取遠端庫的master分支儲存到本地master(由於當前分支為master,所以本地分支省略了),也可以拉取遠端庫的develop分支並儲存到
本地develop分支:
但是,這種方法的拉取並不安全,他會直接覆本地同名檔案,而並沒有徵求使用者的同意,下面的方式相對是安全的:
git fetch的格式與pull類似。但是fetch後,你無論是用git status還是git log都看不到拉取的檔案,這是因為,fecth建立的是引用,你可以通過
git log FECTCH_HEAD命令檢視遠端分支的更改,如果決定接受同步,可以輸入git merge origin/master來合併分支。
第八節 分支策略與工作流:
本節我們將簡單的模擬一個開發專案,以展現git在團隊開發中的強大管理功能,在模擬中,讀者應將該模擬想象成一個龐大的開發專案,關注
分支策略,分工模式等。
在這之前,我們先來了解最基本的分支策略規定,由於現實開發的需要,每個團隊可能採用的分支方式都有差異,但基本上都基於下面的規則:
master:主分支,永遠是最穩定的分支,不應該直接在該分支上進行開發,該分支在每一時刻都是作為某個版本的產品供使用者使用。
develop:開發分支,從master中分離出來,用於存放開發者寫的、相對穩定的、具有一定功能的程式碼。當該分支功能集全並測試後,合併到master分支。
以上兩個分支在遠端和本地都存在。
feature:功能分支,開發者的主要陣地,是開發者為開發某個功能模組,而在本地從develop分支分離出的分支,當功能寫完後,合併到develop分支,並
刪除feature分支。
hotfix:修復分支,當已發行的版本存在bug需要修復時,從master分支分離出,完成修復後,合併到master與develop分支,並刪除hotfix分支。
release分支:預釋出分支,從develop分離,新版本釋出前的調整與測試分支,可以進行細小的bug修復,修復完後,合併到master和develop分支,版本發
布後,刪除改分支。
現在,讓我們通過一個簡單的例項瞭解分支策略與工作流。
1.boss在github上建立了一個專案倉庫,以提交readme.txt初始化倉庫,此時已經有master分支了,boss還要給員工們(張三,李四)分配develop分支,這
些都可以在github上直接操作。
2.下面boss,提交了一份已經寫好的index.html檔案:
3.員工張三,李四分別克隆倉庫(克隆只會克隆master分支),並拉取了develop分支(以張三為例):
4.張三,李四分別從本地develop分支上分離出feature分支,並開發自己的功能模組,開發完成後合併到本地和遠端的develop分支(以張三為例):
遠端狀態:
5.假如李四寫得較慢,當張三提交develop後,李四需要先將develop再拉取一下,更新自己的develop和feature,才能提交:
得知遠端develop有更新後,先更新後commit:
遠端狀態:
6.此時,版本1的所有功能都開發完畢,boss在本地建立realease分支進行測試,而此時員工又可以進行版本2功能的開發,我們來看一下最終版本1的公佈過程:
打上v1.0的標籤,以便之後的跟蹤:
檢視遠端狀態:
7.然而,正當員工們興致勃勃地開發下一個版本時,有使用者抱怨v1.0的一個bug,而距v2.0成功開發完成還有很長時間。為了儘快解決這個情況,boss決定讓張三
放下功能模組的開發,來解決這個bug:
如上圖,如果直接先git add再切到其他分支來修復bug,會使得feature3.js也被跟蹤,此時明智的方法是使用 git stash:
然後張三就可以修改bug了,在修改完後,合併master分支,併發布v1.1:
終於,bug修復完了,張三又可以高高興興地去開發他的功能模組了:
後記:
到此git的學習結束了,但是你只是入門而已,還需要不停地實踐與學習去感受git與github的魅力,比如瀏覽學習github上優秀的開原專案,git高階合併等等。
下面我列出了一些可以參考學習的網站,希望能進一步幫助你:
- https://blog.csdn.net/ouyang_peng/article/details/54981671
- https://www.cnblogs.com/yaks/p/5666400.html
- https://gitee.com/progit/
- http://rogerdudler.github.io/git-guide/index.zh.html
最後,感謝讀者的閱讀,有不當之處,望請包涵!