Git新手入門教學 – part 2

延續先前的Git新手入門part 1,接下來讓我們看看如何把程式碼推到雲端上吧!

3. 推送程式碼至Remote端 (Push/Pull)

在Local端寫了這麼久,來試試看將Local端的程式碼推到GitHub網站上吧!打開https://github.com/ 網站,登入後找到首頁的按鈕:

按下去後,在GitHub上創建一個和本地端名稱相同的資料夾,專案描述可寫可不寫、權限設為開放、README不用勾選,最後按下 :

創建完畢後,我們會進到這個頁面:

當然你可能會想,若我們同時修改Remote端和Local端的檔案、改到同一行程式碼的時候該怎麼辦? 多說無益,直接來試試看吧!

將hello.txt檔案打開,在Remote端的第三行加入一排的驚嘆號「!!!!!!」、再打開Local端加入一排的問號「?????」。

接下來一樣透過和git commit -m,將Local端的程式碼送進Repository。有趣的來了,當我們將輸入 git pull 將程式碼從Remote端拉下來到Local端這邊時:

$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/Lynn19931205/project_1
   260b7de..957b721  master     -> origin/master
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.

 

咦發生什麼事了? 看到最後一行了嗎,Git表示:安安你們有一些衝突(conflicts),待解決完我才會幫你們成功把Remote端的東西融合到Local端這邊噢。先來打開Local端的hello.txt檔案:

咦?! Git很體貼地將程式碼衝突的地方標起來、兩款程式碼都放上去,讓開發者決定要留哪一個版本、或是直接開發出第三個版本。

經過一番掙扎之後… 我們下了個艱難的抉擇──留下問號「?????」,並把其他程式碼都刪除乾淨。

最後再一次git commit、git add,最後用git push將目前這個版本「推送」到Remote端 (一樣須輸入GitHub帳號密碼)。

這時回到GitHub網站重新整理,可以發現…Remote端的程式碼從驚嘆號變成最新修改完成的問號了!

git04.jpg

IT’S DEFINITELY MAGIC!!!

4. 切換(checkout), 開分支(branch)與融合(merge)

在文章的一開始我們提到,Git作為分散式版本管理系統的好處是不需仰賴中央單一一條主幹道開發,可根據開發需求、隨時在某一時間點開分支(branch)獨立開發某一項功能,待開發完成後再融合(merge)回去主幹道。

主幹(master)與分支(branch)是稱呼專案的主要版本和分支版本。在Git第一個建立的專案版本會被稱為master版本。

然而實際上master也僅是其中一條branch,所有branch間的關係都是平等的、彼此間無主從關係。一般習慣將穩定版本稱主幹,其餘的變動、開發中版本則都稱作分支。

開branch的方式非常簡單,直接輸入git branch 即可。

$ git branch branch_a

 

不過這代表著什麼意思呢? 請看下圖:

目前master幹道上有五個commit的版本;若沒有指定要回溯至哪一個歷史版本,branch就會採用最新一次commit的版本。 但若我們想切到某一個commit版本開一條branch時,該怎麼做呢?

branch.jpg

我們可以先輸入git log查看所有commit的歷史紀錄:

$ git log 
commit 372466ead9e54fd3a464cb85d78cd5304f335bc4 Merge: 6183031 957b721 
 Author: Lynn19931205  
 Date: Wed Sep 7 23:35:26 2016 +0800 
 
   Final Edit   
 
commit 957b721541d834fb7a71157f0401bdd013ea6e08
 Author: Lynn 
 Date: Wed Sep 7 23:23:16 2016 +0800 
 
   Update hello.txt 
 
commit adb3238e29668c95130c1e6e82b5bab3faef5489
 Author: Lynn19931205 
 Date: Wed Sep 7 20:30:07 2016 +0800 
 
   Add a if statement 
 
commit 8a85094b22edf4184e7228c3f849807dd7eed2c9
 Author: Lynn19931205 
 Date: Wed Sep 7 19:07:21 2016 +0800 
 
   Add new line I wanna fly 
 
commit 0dc97a8057e1f30139729ce2316f5be966a65ef2
 Author: Lynn19931205 
 Date: Wed Sep 7 18:32:32 2016 +0800 
 
   Add a line.

 

就決定回到第三個commit的版本好了! 選好回溯的時間點後,發動時光機git checkout的威力(checkout後面輸入commit代碼至少6碼);待checkout過去之後,就可以開一條branch了:

$ git checkout adb3238

$ git branch branch_a

 

但這邊我們只是先建立了一個branch噢,實際上我們人還待在master這條幹道上。

因此我們必須利用checkout的另外一個功能、也就是切換各條branch的功能! (別忘了master也只是其中一條branch)。輸入git checkout

$ git checkout branch_a 
Switched to branch 'branch_a'

 

這時候可以發現,我們的所在位置已經從master切換到branch_a這條分支了!

Lynn@LYNNCHEN ~/desktop/project_1 (master) 

Lynn@LYNNCHEN ~/desktop/project_1 (branch_a)

 

輸入git branch -a可以查看目前我們開的所有branch:

$ git branch -a      
branch_a* master  remotes/origin/master

 

當我們不想要這條branch時,可以用git branch -d 刪除:

$ git branch -d branch_a

 

在branch開發了一段時間後,終於完成想要的功能了! 此時可以把branch再融合回去主要的開發幹道上。

首先必須利用checkout回到想要merge過去的主幹道上;比如在此例中我們用git checkout回到master線上之後,再輸入要merge過去的branch名稱git merge

$ git checkout master 
Switched to branch 'master' 
 
$ git merge branch_a

 

由於我們說過master也只是一條branch、和所有branch彼此關係平等,因此要checkout到branch_a、再merge master過來也是可行的,端看開發者需求。

若顯示merge failed時,可能發生了主幹道和分支有同一行程式碼的衝突。

此時就和我們在介紹push/pull時遇到Local端和Remote端程式碼衝突的情形相同,Git會告訴我們哪些地方彼此merge有衝突,待開發者一一解決後再重新merge一次即可成功。

※ 最後介紹一個好用的小指令:help

一路以來常常遇到一個命令後面可以接更多不同的命令組合,如:git commit -a、git commit -m、git commit -e… 或是git checkout -a、git checkout -d、git checkout -f…當族繁不及備載、難以記誦時,只要將help萬能小幫手只要謹記在心便可行遍天下:

$ git  --help
$ git help

 

上述兩種指令的功能完全相同,比如查詢git checkout –help或是git help checkout,就可以查到一連串關於checkout的應用:

git checkout [-q] [-f] [-m] [] 
git checkout [-q] [-f] [-m] --detach [] 
git checkout [-q] [-f] [-m] [--detach] 
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] ] [] 
git checkout [-f|--ours|--theirs|-m|--conflict=

 

若您有成功看完全部內容,真的辛苦了。Git新手教學就到這裡。

今天,我們學到了:

  • 什麼是版本控制系統
  • 什麼是Git和它的優勢
  • 如何clone下來別人的專案或建立自己的專案
  • Git檔案的三種狀態
  • 將檔案提交入暫存區Staging Area或Repository
  • 將檔案提交上Remote端、開branch和merge回去並能解決衝突(conflicts)。

Git的進階功能還有許許多多:

git commit –amend, git rebase -i, git stash, git tag, git cherry-pick…

只需要熟記基礎指令、待開發有需要時再去查詢相關指令即可。

事實上,開發者的Git學習狀態多大同小異地符合以下pattern:
  • 先複製簡單指令
  • 需要更多的功能
  • 開始想辦法搞懂之前複製的指令
  • 被他人亂搞,開始研讀更深入的指令
  • 無緣無故精通了,把 Git 玩透一遍
從複製貼上開始指令碼開始,讓我們一步步精進、有朝一日成為Git大神吧!
本系列完整集數