雜記:Git與Github簡單使用

weixin_34232744發表於2017-09-22

關於版本控制系統(即VCS:Version Control Systems)

歷程:什麼是版本控制系統(VCS)?
牆薦:《Pro Git》中文版(實際上這本書已經夠了)
阮老師的:Git遠端操作詳解
Git之刪除本地倉庫
廖雪峰老師:Git教程

一些命令:

git init

建立一個空git倉庫或重新初始化現有的git倉庫

1666407-6c25beeb1576954c.jpg
菜鳥教程 git init

1.需要在本地內建倉庫,push到Git時,使用git init初始化,就可以變為.git的倉庫了。初始化後,在當前目錄下會出現一個名為 .git 的目錄,所有 Git 需要的資料和資源都存放在這個目錄中。不過目前,僅僅是按照既有的結構框架初始化好了裡邊所有的檔案和目錄,但我們還沒有開始跟蹤管理專案中的任何一個檔案。


git clone

將倉庫儲存到新目錄中
如果想對某個開源專案出一份力,可以先把該專案的 Git 倉庫複製一份出來,這就需要用到 git clone 命令。如果你熟悉其他的 VCS 比如 Subversion,你可能已經注意到這裡使用的是 clone 而不是 checkout。這是個非常重要的差別,Git 收取的是專案歷史的所有資料(每一個檔案的每一個版本),伺服器上有的資料克隆之後本地也都有了。實際上,即便伺服器的磁碟發生故障,用任何一個克隆出來的客戶端都可以重建伺服器上的倉庫,回到當初克隆時的狀態

1666407-e299015f0fd04281.jpg
菜鳥教程 git clone

git status

檢查當前檔案狀態

1666407-286f1a0c4761289f.jpg
菜鳥教程 git status
1666407-daa08c61fc6c9ef0.jpg
《Pro Git》git status

git add .

跟蹤新檔案

1666407-10a8b64e0a19648f.jpg
《Pro Git》git add .
1666407-6c852319fc43c6de.jpg
修改未暫存的 a.md

git diff

1666407-6f0aea533a208b32.jpg
菜鳥教程 git diff
1666407-a621b19f71707406.jpg
《Pro Git》git diff
1666407-be1ac022959ce322.jpg
《Pro Git》git diff
1666407-090e7c6d15b07391.jpg
《Pro Git》git diff

git commit

提交更新

1666407-ff5ebb5f50e35f7a.jpg
《Pro Git》git commit
1666407-ce144b19ff397990.jpg
《Pro Git》git commit

還有很多命令,這裡就不不一一例舉了。

開始使用Git

1666407-77aa13b7356391f8.jpg
《Pro Git》

對於任何一個檔案,在 Git 內都只有三種狀態:已提交(committed),已修改(modified)和已暫存(staged)。已提交表示該檔案已經被安全地儲存在本地資料庫中了;已修改表示修改了某個檔案,但還沒有提交儲存;已暫存表示把已修改的檔案放在下次提交時要儲存的清單中。
由此我們看到 Git 管理專案時,檔案流轉的三個工作區域:Git 的工作目錄,暫存區域,以及本地倉庫。
每個專案都有一個 Git 目錄(譯註:如果 git clone 出來的話,就是其中 .git 的目錄;如果 git clone --bare 的話,新建的目錄本身就是 Git 目錄。),它是 Git 用來儲存後設資料和物件資料庫的地方。該目錄非常重要,每次克隆映象倉庫的時候,實際拷貝的就是這個目錄裡面的資料。

從專案中取出某個版本的所有檔案和目錄,用以開始後續工作的叫做工作目錄。這些檔案實際上都是從 Git 目錄中的壓縮物件資料庫中提取出來的,接下來就可以在工作目錄中對這些檔案進行編輯。
所謂的暫存區域只不過是個簡單的檔案,一般都放在 Git 目錄中。有時候人們會把這個檔案叫做索引檔案,不過標準說法還是叫暫存區域。

基本的 Git 工作流程如下:
在工作目錄中修改某些檔案。
對修改後的檔案進行快照,然後儲存到暫存區域。
提交更新,將儲存在暫存區域的檔案快照永久轉儲到 Git 目錄中。
所以,我們可以從檔案所處的位置來判斷狀態:如果是 Git 目錄中儲存著的特定版本檔案,就屬於已提交狀態;如果作了修改並已放入暫存區域,就屬於已暫存狀態;如果自上次取出後,作了修改但還沒有放到暫存區域,就是已修改狀態。到第二章的時候,我們會進一步瞭解其中細節,並學會如何根據檔案狀態實施後續操作,以及怎樣跳過暫存直接提交。


配置使用者資訊

第一個要配置的是你個人的使用者名稱稱和電子郵件地址。這兩條配置很重要,每次 Git 提交時都會引用這兩條資訊,說明是誰提交了更新,所以會隨更新內容一起被永久納入歷史記錄:
$ git config --global user name "user name"
$ git config --global user email user@example.com

檢查已有的配置資訊,可以使用 git config --list 命令:

1666407-b6e40d23c4022fcc.jpg
git config --list

當不清楚命令時,可order help

1666407-1392b8b264da87d8.jpg
《Pro Git》

接下來我們在Github上新建一個Repository
一般有兩種方法可以生成,一種是直接在遠端生成,然後clone到本地(working directory)。另一種是在本地初始化好,最後上傳到遠端(git directory)

遠端生成:

1666407-6036f5fa6d788ef4.jpg
New repository

當你勾上Initialize this repository with a README選項時,倉庫自動生成.git檔案,此時才算是一個真正版本控制。

clone到本地

1666407-40cd347495312550.jpg
微信截圖_20170923051349.jpg

可以使用SSH方式,也可以使用HTTPS,這裡使用HTTPS。
克隆倉庫的命令格式為 git clone [url]

1666407-f9dc79ec9ac0cf0c.jpg
git clone

這會在當前目錄下建立一個名為Test的目錄,其中包含一個 .git的目錄,用於儲存下載下來的所有版本記錄,然後從中取出最新版本的檔案拷貝。如果進入這個新建的 Test 目錄,你會看到專案中的所有檔案已經在裡邊了,準備好後續的開發和使用。如果希望在克隆的時候,自己定義要新建的專案目錄名稱,可以在上面的命令末尾指定新的名字:

1666407-8853c487cc41d684.jpg
更改專案名字

這樣clone下來的就不是叫Test了,而是Mytest

1666407-7aa4386231da024c.jpg
已跟蹤 or 未跟蹤

檢查當前檔案狀態
git status

1666407-7ac56b885106846b.jpg
git status

說明現在的工作目錄相當乾淨。換句話說,所有已跟蹤檔案在上次提交後都未被更改過。此外,上面的資訊還表明,當前目錄下沒有出現任何處於未跟蹤的新檔案,否則 Git 會在這裡列出來。最後,該命令還顯示了當前所在的分支是 master,這是預設的分支名稱,實際是可以修改的,現在先不用考慮。
現在我們更改一下README檔案
vim README.md後,再次git status

1666407-dab1c8b4042b2526.jpg
git status

此時,Git發現了我們修改的檔案,但是,此時README並沒被跟蹤,所以需要手動跟蹤檔案,Git也提示:(use "git add" and/or "git commit -a")

跟蹤新檔案:git add

使用命令 git add 開始跟蹤一個新檔案。所以,要跟蹤 README 檔案,執行:git add README,也可以:git add .
加點表示,Git會遞迴地將你執行命令時所在的目錄中的所有檔案新增上去,所以如果你將當前的工作目錄作為引數,它就會追蹤那兒的所有檔案。

現在,再次重申一下那幅圖,我修改了一點。

1666407-7afaf8d94d184acc.jpg
working area —— staging area

Git中的檔案只有兩種狀態中的其中一種,即不是已跟蹤就是未跟蹤,已跟蹤檔案就是圖中藍色區域部分,可能是已修改、未更新,或已放入暫存區。
git add所做的就是跟蹤檔案,並放入暫存區:

1666407-51cedc9e2ac4d5d6.jpg
git add後,重新git status

此時我們git commit,就會把暫存區內所有檔案的更新情況,版本資訊上傳至.git版本庫中了,這次版本更新就完成了。

但是,假設我們在commit之前修改了已跟蹤的README檔案,會發生什麼呢?

1666407-c4d44c0b186c994f.jpg
修改了README檔案

檢視狀態發現, 檔案出現了兩次!一次算未暫存,一次算已暫存。
實際上 Git 只不過暫存了你執行 git add 命令時的版本,如果現在提交,那麼提交的是新增註釋前的版本,而非當前工作目錄中的版本。所以,執行了 git add 之後又作了修訂的檔案,需要重新執行 git add 把最新版本重新暫存起來。

檢視已暫存和未暫存的更新 git diff
實際上 git status 的顯示比較簡單,僅僅是列出了修改過的檔案,如果要檢視具體修改了什麼地方,可以用 git diff 命令。稍後我們會詳細介紹 git diff,不過現在,它已經能回答我們的兩個問題了:當前做的哪些更新還沒有暫存?有哪些更新已經暫存起來準備好了下次提交? git diff 會使用檔案補丁的格式顯示具體新增和刪除的行。
要檢視尚未暫存的檔案更新了哪些部分,不加引數直接輸入 git diff:

1666407-681f8d2e0b4f5716.jpg
git diff

請注意,單單 git diff 不過是顯示還沒有暫存起來的改動,而不是這次工作和上次提交之間的差異。所以有時候你一下子暫存(git add)了所有更新過的檔案後,執行 git diff 後卻什麼也沒有,就是這個原因。

提交更新git commit
現在的暫存區域已經準備妥當可以提交了。在此之前,請一定要確認還有什麼修改過的或新建的檔案還沒有 git add 過,否則提交的時候不會記錄這些還沒暫存起來的變化。所以,每次準備提交前,先用 git status 看下,是不是都已暫存起來了,然後再執行提交命令 git commit:
git commit
種方式會啟動文字編輯器以便輸入本次提交的說明。(預設會啟用 shell 的環境變數 $EDITOR 所指定的軟體,一般都是 vimemacs。當然也可以按照第一章介紹的方式,使用git config --global core.editor命令設定你喜歡的編輯軟體。)

編輯器會顯示類似下面的文字資訊(本例選用 Vim 的屏顯方式展示):

1666407-66746da0013e0f9e.jpg
提交資訊

或者也可以使用git commit -m "XXX",-m 引數後跟提交說明的方式,在一行命令中提交更新:

1666407-c2f45dc7b77fd594.jpg
git commit -m

好,現在你已經建立了第一個提交!可以看到,提交後它會告訴你,當前是在哪個分支(master)提交的,本次提交的完整 SHA-1 校驗碼是什麼(fbee2c0),以及在本次提交中,有多少檔案修訂過,多少行添改和刪改過。

跳過使用暫存區域
儘管使用暫存區域的方式可以精心準備要提交的細節,但有時候這麼做略顯繁瑣。Git 提供了一個跳過使用暫存區域的方式,只要在提交的時候,給 git commit 加上 -a 選項,Git 就會自動把所有已經跟蹤過的檔案暫存起來一併提交,從而跳過 git add 步驟。

檢視提交歷史:
在提交了若干更新之後,又或者克隆了某個專案,想回顧下提交歷史,可以使用 git log 命令檢視。

1666407-51c3cd945034dcbe.jpg
git log

預設不用任何引數的話,git log 會按提交時間列出所有的更新,最近的更新排在最上面。看到了嗎,每次更新都有一個 SHA-1 校驗和、作者的名字和電子郵件地址、提交時間,最後縮排一個段落顯示提交說明。

關於遠端倉庫

檢視當前的遠端庫
git remote
要檢視當前配置有哪些遠端倉庫,可以用 git remote 命令,它會列出每個遠端庫的簡短名字。在克隆完某個專案後,至少可以看到一個名為 origin 的遠端庫,Git 預設使用這個名字來標識你所克隆的原始倉庫:

1666407-a27c3c5a6486b821.jpg
git remote

推送資料到遠端倉庫

專案進行到一個階段,要同別人分享目前的成果,可以將本地倉庫中的資料推送到遠端倉庫。實現這個任務的命令很簡單: git push [remote-name] [branch-name]。如果要把本地的 master 分支推送到 origin 伺服器上(再次說明下,克隆操作會自動使用預設的 master 和 origin 名字),可以執行下面的命令:git push origin master

1666407-7129f760495d0c7d.jpg
git push origin master
1666407-f6cfc9a823bc9360.jpg
推送至遠端

如果,在你推送到遠端之前有人在你的遠端倉庫上進行了修改,會出現什麼呢?

1666407-eaeb783edd1df6cb.jpg
模擬遠端倉庫上的一次更新
1666407-8bea01677c8c20c8.jpg
本地再次修改README檔案

現在我們將本地更新的資料跟蹤暫存,push到Remote Repository

1666407-30e32df44a345b2b.jpg
git commit之前的檔案更改狀態

可以看到,有兩個操作未被跟蹤,未被暫存,也沒有進入本地版本庫中。現在我們將它們add並commit。

1666407-8700c91ebfc77106.jpg
push失敗

Updates were rejected because the remote contains work that you do:大概意思(原諒我英語不好)就是遠端倉庫中包含了一些本地沒有的檔案(更新)。

此時,我們需要抓取遠端倉庫中的資料,和本地同步之後,再進行修改上傳。

從遠端倉庫抓取資料

git pull origin master
使用 git pull 命令自動抓取資料下來,然後將遠端分支自動合併到本地倉庫中當前分支

1666407-ae84baa0c5efb5f0.jpg
用vim檢視更新

pull回來之後,用vim編輯器開啟,就可以看到,遠端倉庫的檔案和本地檔案更新的區別。
稍作改動後,我們儲存,就可以commit,push到遠端了。


1666407-b963f6d9ccf3c0e2.jpg
git push
1666407-26a558f32f285d12.jpg
github repository

本地建立倉庫並初始化
有兩種取得 Git 專案倉庫的方法。第一種是在現存的目錄下,通過匯入所有檔案來建立新的 Git 倉庫。第二種是從已有的 Git 倉庫克隆出一個新的映象倉庫來。
在工作目錄中初始化新倉庫
git init

1666407-472c96f78a383eea.jpg
初始化倉庫
1666407-8e64240abcb19e71.jpg
github added Web Repository
1666407-d06aa9c7ea132bc2.jpg
一些資訊
1666407-70d1cab4acfc77b0.jpg
按照上圖提示push
1666407-b2ff7e6f62be5cc2.jpg
新的專案

關於簡單的分支概念

當多人協同工作,來開發、維護一個專案時,包含ABC三個模組(功能),程式設計師No.1—A,程式設計師No.2—B,程式設計師No.3—C。一號程式設計師就可以從初始專案上拉一個新分支開發A模組,同樣的2、3號程式設計師也可以拉取屬於自己的開發分支,此時,誰先完成了自己的開發任務,就可以直接合併到舊的專案中,不斷迭代......

或者當一個線上專案出現問題,開發者可以返回伺服器所在的分支,並開闢一個新的修復分支,當修復好以後,再把修復分支合併進來,再推送到伺服器上.......
不是很準確的描述,但這正是Git最強大的地方。

檢視所有分支git branch -a

1666407-e78255f9f6bc2c39.jpg
git branch -a
藍色:本地分支
紅色:遠端分支
 *  :當前所處分支

新建分支git branch

1666407-82d78d02a0ad4341.jpg
新建分支

切換分支:

1666407-7b8edb0d14ee30f7.jpg
切換分支

檢視Dev分支內部檔案,可以發現是和master分支是一樣的。

1666407-a5d64ff660a8989e.jpg
檢視分支檔案

現在我們模擬一下,有人在新分支內進行更新:

1666407-83a4aca9423093dc.jpg
更新分支Dev

加入了新檔案,並跟蹤暫存,提交。

在切回原分支master上(想象成一個樹幹和樹枝會更形象):

1666407-3aec9723d00a9f1a.jpg
master分支

可以看到,master分支上並沒有index.html檔案,這可是同一個資料夾下哦。

這就是分支簡單概念。

現在需要推送這個新分支了。

1666407-bee1194ec5955025.jpg
推送新分支到remote
1666407-148edda0602fdeb3.jpg
推送成功了

有時候可能需要你更改上傳倉庫URL。

可以想象一下,master是線上版本,拉一個Dev分支後,進行開發,測試。無誤後,我們需要將Dev分支合併到原master上,如何合併呢?
首先切換到需要合併的分支上,這裡是master分支,然後使用git merge命令

1666407-dad76f54903e7c75.jpg
git merge

此時,master分支內,也有index.html檔案了。
再git push一次,此時就可以釋出上線了,依舊是master分支,這個版本。

1666407-5bfaaf215438ab13.jpg
github上的master

PS:之前對origin、master這兩個概念搞不清,現在倒是清晰了一些,origin就是這個repository預設名字,預設遠端庫的名字。可以理解為一個指標,當然也可以更改,而master就是這個程式碼庫的一個分支。
來自知友更正確的回答


衝突

有時候合併操作並不會如此順利。如果在不同的分支中都修改了同一個檔案的同一部分(例舉問題,實際可能沒那麼簡單),Git 就無法乾淨地把兩者合到一起(譯註:邏輯上說,這種問題只能由人來裁決。)

現在有人修改了master分支上的README。


1666407-83a2f67a634b411c.jpg
遠端修改master上的README

這時,我們在本地更改了Dev分支,重新add,commit,並push。

1666407-c104e18c8e0110a8.jpg
1666407-1394ceea551cecb4.jpg
一些操作

本地下,更改Dev分支README檔案,並add,commit。切換到master分支後,將Dev分支合併到master裡,使得兩個分支內容一樣,最後add,commit,push。
出現了問題,遠端包含了一些本地沒有的內容,Git需要你手動解決這些矛盾。

那就git pull

1666407-5c204e05beb98dc0.jpg
merge conflict合併衝突了

Git 作了合併,但沒有提交,它會停下來等你解決衝突。要看看哪些檔案在合併時發生衝突,可以用 git status 查閱:

1666407-25291a28a72cf8c9.jpg
git status檢視衝突檔案

任何包含未解決衝突的檔案都會以未合併(unmerged)的狀態列出。Git 會在有衝突的檔案里加入標準的衝突解決標記,可以通過它們來手工定位並解決這些衝突。可以看到此檔案包含類似下面這樣的部分:

1666407-3b0b5b5c19c03958.jpg
衝突標記

可以看到 ======= 隔開的上半部分,解決衝突的辦法無非是二者選其一或者由你親自整合到一起。
最後整理好後,記得git add .

1666407-c05e150dfbf7519a.jpg
最終上傳
1666407-da05fece3d75b08a.jpg
github master分支更新

push後,遠端倉庫也做了更新。

1666407-0035c9a41ddafd56.jpg
merging
PS:注意到,之前的衝突時的push,藍色字型時MERGING,表明這實際上做了merge處理?(求大神告知)。
可以自己做更多的嘗試,本地修改,遠端修改,不同分支處理,就當是自己製造麻煩,然後尋找方法,這是最好的嘗試了。

在《Pro Git》文件中也有這樣的說明:
遇到衝突時的分支合併

1666407-57bb4b6ea17b206d.jpg
from《Pro Git》

引發衝突的場景還有很多,遇見更多的問題,並解決,才能更好的理解這一概念,使用好這一工具。

這篇文章只是很簡單的入門了一下Git,當做自己的學習點滴紀錄,Keep moving吧~!

相關文章