什麼是版本控制?
不知道你們是否曾經有遇過這種狀況。寫完code後要儲存,但有太多版本,或許是昨天、前天,或更久之前寫的。於是聰明的你就把這些不同的版本命名成了…
單人作業的時候,這樣看似沒什麼問題。但只要遇到團隊作業,有各種不同的人在不同的部分寫不同的code,這就會變成不是很好的方法。
或者你想要前後對照前天跟今天你在同一份文件中究竟做了什麼變動,想知道昨天跟今天新增/減少了那些檔案,這種方法也沒辦法提供有效的幫助。
也就是因為這樣,才催生出了版本控制(Version Control)的想法。
根據維基百科的簡單定義,
藉由版本控制能在軟體開發的過程中,確保由不同人所編輯的同一程式檔案都得到同步,是一種軟體工程的技巧
版本控制主要分有兩種:
- 集中式(ex: SVN)
- 分散式(ex: Git)
而今天主要要介紹的git就屬於分散式的版本控制系統。
Git? Github? 能吃嗎?
Git是由大名鼎鼎的Linux之父Linus Torvalds所開發的。原本是為了更好地管理Linux kernel的source code,想不到就這樣發展成現在工程師們每天都要用到,必備的技能。
剛開始進入這塊的人應該會對git、github,或是gitlab等git字輩的名詞給搞得頭暈目眩。
簡單來說,git是版本控制系統,而github、gitlab等網站則是在網路上提供遠端儲存空間remote repository(下面會更詳細解釋這是什麼),讓我們只要能連上網路就能隨時存取自己的Code。
git在記錄版本之間的更動、新增、刪除的方式採用的是快照(snapshot)。git採用這種方式,只會紀錄版本與版本之間的相異之處。如此一來就能讓速度提升,也讓其所占的體積減小了不少。
p.s. 常見的提供網路原始碼remote repository的網站有:
- Github
- Gitlab
- Bitbucket
Git工作流程介紹
在一般日常應用中,常會用到的基本觀念有:
工作區、暫存區、local repository、remote repository。
接下來我會用學生的書桌、辦公室的辦公桌來比喻git正向、反向的工作流程。
正向流程(儲存到repository中):
1.工作區workspace
就是你的工作區域,對檔案的任何更動會第一手的直接反應在這邊。這時候檔案會處於tracked、untracked、modified、unmodified其中之一的狀態。
可以把工作區想像成你的書桌、辦公桌之類的桌子。
2.暫存區staging area
經過$git add
之後,檔案會跑到暫存區內。這時候檔案會處於staged的狀態。
可以把暫存區想像成你的書包、公文夾、包包之類的,這時文件檔案都還沒被正式存入資料庫中,而是準備被放到資料庫中。
3.local repository
經過$git commit
之後,檔案就會被正式地存入local repository之中。
在這邊可以把local repository想成你的書櫃、公文庫等等,也就是一個存放資料的資料庫。
4.remote repository(像github、gitlab等網站)
經過$git push
之後,本地端的檔案就會被存入remote repository,像是Github、Gitlab之類的網站。而那些網站上面的狀態就與你push時的狀態是相同的。
逆向流程(從repository中取回最新資料):
1.remote repository(像github、gitlab等網站)
存有檔案最新的狀態,所以才需要從remote repository取回,以更新本地的檔案。
可以想成要從書櫃、公文庫等資料庫中取回最新的資料來進行工作。
2.工作區workspace
經過$git pull
後,檔案就會被更新成到remote repository的最新狀態。
Git檔案狀態-一張圖輕鬆理解
Git使用情境及指令
以下我想把git常用的指令分為幾個使用情境來介紹,畢竟git的指令實在是太多了。如果要一一介紹恐怕一篇是寫不完的,所以我粗略的分為了三個部分。
- 檢查git管理的目錄的狀態
- 開始專案開發
- 將開發完的成果同步到remote repository
- Branch分支
情境一-檢查git管理的目錄的狀態
$git status
如果想要檢查目前被git所管理的目錄內檔案是否有更動的話,可以用這個指令。
紅色框起來的master代表現在位於master這個分支之下。
這個指令可以看到目前這個資料夾的狀態。值得一提的是那個origin/master分支指的是remote repository的master分支,也就是在Github上的master分支。
修改了一個原本就存在,也就是本來為tracked狀態的檔案後,他的狀態會變成modified。
新增了一個檔案後,其狀態則會是untracked,需要透過$git add
讓他加入git的管理。
$git log
如果想在terminal中查看過往的commit紀錄,可以用這個指令。後面沒加任何參數的話,會將所有資訊詳細的列出來。
你也可以打$git log --oneline
,他只顯示commit訊息以及commit id,以一行的方式精簡地顯示出commit歷史。
$git diff
想知道專案檔案之間的差異就能用這個指令。
沒加任何參數直接打$git diff
,比較的是工作區workspace以及暫存區staging area的差異。
這邊給一個實際的例子。首先我先建立了一個HI的檔案,將他加入git的管理,並且先用$git add
把他加入到暫存區staging area內,裡面內容如下。
接著我加了第二行,就變成下面這樣。
最後用$git diff
就能夠顯示出目前工作區與暫存區,HI這個檔案究竟有什麼差異。
加入其他參數:
$git diff [檔案名稱]
$git diff [commit ID]
$git diff [commitA ID] [commitB ID]
情境二-開始專案開發
如果你在Github上還沒有一個repository的話,可以先去Github上申請一個帳號,並建立一個repository,然後再看看下面關於git clone
以及git pull
的教學。
剛建立好的repository長的會像下面這樣。
如果你什麼檔案都還沒有的話可以按照create a new repository的步驟,他的順序是先用echo
建立一個README.md,然後再把那個檔案push到Github上。
如果已經有一些東西的話,就按照push an existing repository的步驟就行了,那兩行其實也只是設定到底該把資料push到哪個remote repository而已。但要記得先把那個資料夾加入git的管理之下,再按照git add、git commit、git push的步驟依序來進行。
$git clone [repository url]
開始專案開發時可能需要先從Github等網站先把一些東西下載下來,不論是你自己的還是Github上別的大神的repository都可以。這時候就可以用這個指令。
如果要找URL,先點進去該repository,再按照下圖的教學。
接著就像下面這樣,git clone [repository url]
。
$git pull
或者是先把本地端的東西更新到與remote repository相同的狀態。另外,這個指令深入探究的話,其實就是git fetch
+ git merge。
情境三-將開發完的成果同步到remote repository
$git add
git add 用法:$ git add [檔案名稱]
$ git add .
$ git add *
如果新增/刪除/更新了檔案後,可以用git add
這個指令來將更動存到暫存區staging area之中。不知道自己有沒有對檔案進行更動可以先用上面有講過的git status
來確認看看目前的檔案狀況。
首先我先用git status
確定狀態,發現README.md被刪除了。
所以我接著用git add把這個更動儲存到暫存區staging area內。順道一提,
如果有大量檔案都更動到的話,可以用git add .
或是git add *
一次把所有更動都放到暫存區內。
$git commit
git commit 用法
$ git commit
$ git commit -m "commit訊息打在引號裡面~"
接著就準備把在暫存區staging area內的更動存入local repository!這時候我們需要用到的就是git commit
。
直接用打第一行不加commit訊息的話,會直接跑到預設的文字編輯器內(這邊是vim)。如果知道怎麼使用vim的話,可以直接在這邊加上commit訊息,並且儲存離開就能完成commit了。
如果用第二行的話,直接在後面加上commit訊息,按下enter就能完成commit了!
$git push
git push 用法
$ git push
$ git push [remote repository的URL]
最後一步,就是把儲存在local repository的更動儲存到像Github、Gitlab等等的remote repository。而我們需要用到的指令就是git push
。
一般的情況下,直接打git push
應該就能完成推送更動到remote repository。
但也可能遇到這種情況,沒有設定好該把更動存到哪去。但這時候不用慌張,只要複製紅色那行,再貼上按enter就能成功了。
情境四-Branch分支
如果是初學者的話,一開始可以跳過這個部分。但有些人可能想了解怎麼用,所以以下就簡單介紹一下。想深入了解的話,我推薦參考資源裡面的Learn Git Branching。
另外,要了解branch的話,最好還要先了解Git裡面HEAD是什麼。
$git merge [branch名稱]
將某個指定的branch併入目前你所在的branch。
$git branch
git branch 用法
$ git branch [branch名稱] // 建立分支
$ git branch -d [branch名稱] // 刪除分支
$git checkout [分支名稱]
移動HEAD到該branch,並且查看該branch。
另外,我還想再介紹一個東西-gitignore。專案規模小的時候可能用不太到。但如果專案規模很大,引用了許多套件,像nodejs npm install了一堆套件,這時候不想把那些套件也一起push到remote repository的話,就可以用gitignore。
用法其實很簡單,只要在你的git資料夾內建立一個.gitignore的檔案就行了。
第一次寫了一篇這麼長的技術教學,或許文章編排,教學難易度,內容專業度含量都不夠成熟。但仍希望看過這篇教學的人,無論是新手、老手都能有所收穫。
如果文章中有任何錯誤的地方也歡迎留言回覆,或是Highlight告訴我!
參考資源
這篇寫得很不錯,某天無聊在逛csdn的時候發現的。好處是用中文寫的,可以更好的了解裡面的內容。
如果想更深入了解git branch(分支)到底是什麼的話可以玩玩看這個教學。用視覺化的方式我覺得對於理解branch是個滿不錯的方式。
Git官方文件,擁有最詳盡,有關於各種指令的解釋。