這份 tutorial 會以作業形式教大家如何透過 Git 管理檔案版本並上傳到 GitHub 上,同時也會教一些基本 Linux 指令讓你操作你的系統。Git 和 Linux 指令都是業界程式開發必備的技能,甚至學校作業都能用到,早學早使用!
本次作業包含: 4 個問題。總共預計完成時間為:45分鐘。
Git 是一個免費的 版本控制工具 ,而 GitHub 是一個利用 Git 集合並管理 開源程式專案的平台 ,兩者是完全不同的概念但彼此的關係緊緊相連。簡單來說,GitHub 上會充滿各種程式專案,而開發者可以在線下利用 Git 進行 專案下載(clone) 、 提交修改(commit) 、 上傳更新過的專案(push) 等等。這邊的中文都是我自己尋找的生動詞彙而不是直翻,建議大家記得英文單字就好。
而其中的精華盡在其 版本控制 與 專案合作 的功能:每一次的提交修改都會被記錄下來,也就是如果你發現程式走錯路了,你永遠可以返回之前某個提交點的狀態重新來過;一個專案若有多個開發者,每一個開發者可以各自將專案下載至自己的作業環境中,而在修改過後若想更新 GitHub 上的專案,你必須先 下載其他人新的修改(pull) 並與你的修改 合併(merge) 後才能上傳。
GitHub 亦提供許多其他功能,包括開 Issues 與開發者溝通專案問題,或是渲染(將原始碼轉成易瀏覽的形式) Markdown(一種文字轉網頁 HTML 格式的工具)檔案等等。
現在你在的這個網頁就是 GitHub 上的其中一個專案,你所瀏覽的這篇漂亮的教學文就是以 Markdown 撰寫並渲染成網頁 HTML 格式給你看的!而接下來我們要使用 Git 將作業下載到自己的作業環境,或稱本地端。
- 安裝 Git
- 到 這裡 選擇你的作業系統,下載並安裝。
- Windows:如果在安裝過程中看到系統問是否要選擇 Git Bash Here ,選擇是。Git Bash 可以讓之後所有的操作指令和 Mac / Linux 使用者統一。
- 打開 Terminal (終端機)
- MacOSX:用 Spotlight Search 搜尋 Terminal。
- Windows:桌面按右鍵,選 Open Bash Here 。
- 更換目錄
- MacOSX:建議在 home directory (使用者目錄)進行作業。輸入
cd ~
並 enter。cd
代表 change directory,即更換目錄。~
代表 home directory 的路徑。 - Windows:建議在桌面進行作業。若前一步驟是在桌面按右鍵,那麼打開後的 terminal 即是在
.../Desktop
這個目錄,無須更換。若想在別的目錄進行作業,輸入cd <path>
並 enter。cd
代表 change directory,即更換目錄。<path>
請用目標目錄的路徑取代。
- MacOSX:建議在 home directory (使用者目錄)進行作業。輸入
- 檢查 Git 是否正確安裝
- 輸入
which git
。若有成功安裝,則會印出 Git 程式的路徑。若沒有安裝成功則不會印出任何東西,請尋求幫助。
- 輸入
- 下載此份作業
- 回到 GitHub 此份專案的網頁,點選右上角 Fork,將專案複製一份到自己的頁面。
- 回到自己的頁面底下找到剛剛 fork 的專案。進入後點擊綠色按鈕 Clone or download ,並複製呈現的 URL
- 輸入
git clone <url>
。<url>
請用複製的 URL 取代。 - 輸入
ls
確認作業成功下載。ls
代表 list,即列出當前目錄下的所有檔案與子目錄。若下載成功,會看到git-very-good-tutorial
印出。 - 更換目錄至此專案。這邊請動動腦, 請問要用上面出現過的哪個指令呢?
若成功進入下載後的專案,terminal 的 prompt ($
) 之前顯示的當前路徑會是 .../git-very-good-tutorial
。
- 輸入路徑到一半時,可按鍵盤上的
tab
進行自動完成。 - 在 terminal 按上鍵可以回溯之前輸入過的指令。
- 根目錄(root)是整個系統的最上層路徑,路徑表示為
/
。每下一層目錄,即多一個/
,例如/hello
為根目錄底下的hello
目錄,/hello/world
為根目錄底下的hello
目錄底下的world
目錄,以此類推。 - 路徑分 絕對路徑 與 相對路徑 。絕對路徑即從根目錄(root)開始算起,而相對路徑從當前目錄開始算起。例如在當前目錄
/hello
下,相對路徑world
與絕對路徑/hello/world
同義。 pwd
可以顯示當前目錄的絕對路徑。- 輸入並 enter 太冗了,之後稱作執行。
終於要來正式進行版本控制了。
這邊講解一下 暫存(stage) 和 提交(commit) 的概念。情境是這樣的:塔矢亮針對專案裡的檔案進行了多個修改。塔矢亮跑了 git status
這個指令,檢視一下剛剛的修改:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: A.txt
modified: B.txt
no changes added to commit (use "git add" and/or "git commit -a")
這代表修改的檔案包括 A.txt
及 B.txt
。
但是在提交這些修改之前,塔矢亮想到這兩個修改應該要是不同意義的。A.txt
的修改主要是增加一些註解,而 B.txt
的修改是修正一些 bug。如果這兩個修改同時提交,那未來審視這個專案的修改歷史時會引起混亂。正確的觀念應該是分別提交 A.txt
及 B.txt
的修改。
這時塔矢亮需要先用 git add A.txt
暫存 A.txt
的修改,並用 git commit -m <message>
提交 。為了清楚描述這個修改,塔矢亮必須提供一個 commit message,也就是 <message>
。接著再針對 B.txt
的修改做一樣的事情。
於是塔矢亮這麼做了:
$ git add A.txt
$ git commit -m "Add comments"
$ git add B.txt
$ git commit -m "Fix bugs"
看到塔矢亮這麼做的你,馬上就知道這個 problem 要怎麼完成了。
- 設定 Git 的使用者資料,才能在 commit 中留下紀錄(並找到修改的負責人)。執行
git config --global user.email <email>
和git config --global user.name <name>
,<email>
以你自己的 E-mail 取代,<name>
以自己的名字取代。 Assignment
目錄下有兩份檔案,coffee_or_tea.txt
及dog_or_cat.txt
。用任何編輯器(Notepad++,Sublime,甚至 Word 都行)打開,將出現的問題刪掉,並加上自己的回答(e.g. 刪掉<Coffee or tea?>
,輸入Coffee
)。存檔。- 提交修改 兩次 。兩份檔案的修改分別提交,先提交哪份的修改都可以,並附上 清楚的 commit message 。
- 在
git add
後git commit
前,執行git status
時,暫存的修改會從紅色變綠色。 - 可用
git reset HEAD <file>
將修改從暫存區移除。
剛剛的修改都在本地端,也就是遠方 GitHub 上的專案還處於你剛剛下載時的樣子。這時要更新遠端,就要進行 上傳(push) 。
指令是這樣子的:git push <remote> <branch>
。<remote>
是遠端的端點名,因為一個專案可以有很多的遠端端點。現在這個專案只有一個預設的遠端 origin
。<branch>
是分支,因為一個專案可以開很多分支,但我沒教你。現在這個專案只有一個分支 master
,也就是主分支。
完整的指令便是:git push origin master
- 將剛剛提交的修改上傳到遠端 GitHub。
到 GitHub 重新整理,會看到修改後的檔案們。
其實 GitHub 上是可以直接修改檔案的,普遍是在 GitHub 上修改 Markdown 檔案,因為可以預覽渲染結果。而在遠端修改後,同樣的本地端的檔案仍然不會自動因此改變,所以要 下載(pull/fetch) 修改。
指令跟 push 大同小異:git pull <remote> <branch>
。
- 在 GitHub 網頁上,點進
README.md
。點選 鉛筆圖示(Edit this file) 。 - 至檔案下方心得區中書寫自己的心得。
- 至編輯區下方 Commit changes 表格的第一格寫上 commit message。沒錯,這也是一個 commit!
- 按 Commit changes 提交。
不知道 分支(branch) 依然能夠正常使用 Git,但想像你在某個時間點想為專案嘗試性的加入一些功能,但還不確定是不是真的要採用這個功能,或這個功能是不是真的能夠成功建立。這時你就可以從 master
branch 分一條支線出去,如此一來在分支上不論怎麼亂改,都能無痛換回原本的 master
branch。
先執行 git branch
檢視一下專案目前有的分支:
$ git branch
* master
也就是目前只有一個 master
branch。我們可以用 git checkout -b <new-branch>
來添加分支,<new-branch>
即新的分支名,而 -b
是選擇新增分支(而非只是前往)。現在我們來新增一個分支 new
,然後重新檢視專案目前的分支:
$ git checkout -b new
Switched to a new branch 'new'
$ git branch
master
* new
可以看到星星跑道我們剛剛新增的 new
branch 之前,代表現在在 new
branch。
我們來進行一些修改,例如刪除那兩份檔案。執行 rm Assignment/*
,*
代表目錄下所有檔案。這時看看我們的 git status:
$ git status
On branch new
...
deleted: Assignment/coffee_or_tea.txt
deleted: Assignment/dog_or_cat.txt
...
可以看到檔案被刪除了。這時我們一次提交這兩個修改。執行 git add Assignment/*
暫存修改後,執行 git commit -m "Delete files"
提交。
現在在 new
branch 我們失去了這兩個檔案。我們後悔了,於是決定換回 master
branch 重新來過。
執行 git checkout <branch>
可以切換至 <branch>
,所以要前往 master
branch 要執行 git checkout master
。
檢查一下你的目錄,那兩個檔案回來了嗎?
- 在 GitHub 及本地的兩份檔案
coffee_or_tea.txt
和dog_or_cat.txt
必須被修改。 - 在 GitHub 及本地的
README.md
心得區必須有心得。 - 在 commit history 中應有兩個檔案修改的 commit 和一個
README.md
修改的 commit - Commit message 必須清楚描述此次的 commit
This is awesome!