在學習使用 Git 以前,先來建立它管理版本的概念,Git 系統區分了三階段去紀錄檔案內容,從實體到抽象依序是:「Working tree, Index/Cache, Repository」。
頭尾的 Working tree 和 Repository 分別對應我們「實際操作的資料夾」與「檔案的版本們」,夾在兩狀態之間的 Index 則是一個「可調可控的過程」,這個階段中我們可以安排決定哪些檔案變更要被安置在哪一個檔案版本中。
想像一下, Git 的 Working tree 就是一間工廠,當我們(又名工人)開發程式碼吿一個段落後,下一步就是選取想要留存的產出,送進出貨區 Index 等待包裝。但 Git 的包裝方法比較特別,它會替檔案和檔案的工作空間拍一張照,以後它只要看到照片,就可以重建這個當下。
這個常常被叫做 Commit 的照片紀錄了不同版本的模樣,一個個Commit 又可以依照來源方向串成線,變成像是人類歷史一樣的東西,或更複雜的樹狀結構,讓我們可以遊走在某個關鍵事件還沒發生的 Commit 歷史裡,體驗像是平行時空的開發環境。
話不多說,先來點基礎 Git 指令
一開始,先在版本控制的目標目錄執行 git init
,目錄中會建立 .git 檔案紀錄這些檔案的歷史,如果有不想加入的檔案,可以在目錄裡放入 .gitignore
檔案,並且把打算忽略的檔案名稱新增在此就可以了。
因為 Git 只會認得被設定要加入版本追蹤的檔案,所以每次新增檔案,都需要透過 git add <file>
來把它加入追蹤系統(stage)裡,但如果曾經加入追蹤的檔案,Git 會自動把它標示為 「modified」,這時候,可以透過 git diff
取得變更前後的比較。
確認要進版的對象後,同樣要使用 git add <file>
告訴 Git,想偷懶一點的話可以用 git add .
或 git add --all
一次把所有變更項目加入 stage,但如果不小心誤加了不在當下規劃裡的檔案,可以使用 git reset HEAD <file>
來取消,另一個相似但有危險性的 git checkout -- <file>
則是會捨棄檔案在工作目錄下的變更,也就是上一個 commit 到執行當下這段時間的變更基本上就被捨棄了。
確立了要生成 Commit 的版本後,就大膽地執行 git commit -m "你的Commit訊息"
,就算訊息不小心寫錯也能透過 --amed
來修改。
重點整理
# 初始化
git init
# 比較差異(退出比較請按 q)
git diff
# 把 Untracked files 列入追蹤
git add <file>
# 為 Commit 留下訊息
git commit -m "你的Commit訊息"
# added 紀錄退回(unstage)
git reset HEAD <file>
#
補充:查看目前的檔案狀態與歷史
# 查看當下的目錄狀態
git status
# Git 的歷史
git log
# Git 的單線歷史
git log --oneline
用過才知好
學會基礎的 Git 指令後,有時會因緣際會掉入山洞、拿到武功秘笈,通常這個洞就是開發時的使用需求,因此這裡記錄下幾種使用情境與操作。
設定指令別名 git alias:用來設定一個指令的縮寫版,例如:
git config --global alias.status st
,縮短打字和修改打錯字的時間(如果你是 CLI 用戶的話...)建立臨時版本 git stash :
- 手中有尚未完成的開發工作,但必須臨時切換到其他分支時,可以使用
git stash
會把當下目錄 stage 暫存起來,這時除了 Untracked files 以外, Working tree 會是可以切換到其他分支的乾淨狀態。 - 要回覆被中斷的工作狀態的話,可以先使用
git stash list
確認下要回覆的暫存版本,並透過git stash pop stash@{i}
回復指定的工作狀態。
- 手中有尚未完成的開發工作,但必須臨時切換到其他分支時,可以使用
其他重要的 Git 概念: 其實還有好多重要的 git 觀念不及在本文詳述,比如:「拆掉 Commit 的 git reset」、「合併發生衝突 (merge conflicts) 」、「與遠端互動:Push & Pull」
學習資源推薦
本文寫成時,參考了下列兩個系列文章的內容,前者是高見龍的「為你自己學 Git」,淺顯易懂的舉例應該是許多人(包含我)的啟蒙書,適合初學 Git 的讀者。
後者在是在收集資料過程中找到的鐵人賽文章「How Git Works」,相關文章對 Git 的深入細節做了很詳細的挖掘,推薦給和我一樣會使用,但對它背後的運作原理不甚熟悉的朋友們。
後記 & 心得
寫這篇文章的動力,是為了還清自己在記事本裡累積的「應做筆記而未做」的項目們,這是第一篇,寫到一個段落後,覺得文章再長就不適合閱讀了,決定暫時停筆,順道對照自己記事本記下的問題。這才發現,有些我自己的疑惑還沒被寫到,這篇文章只達成建立後面討論問題的部分基石,一方面覺得自己的債怎麼越還越多,但換個角度想,也許這也紀錄了自己在無形間往前走的距離。
寫作的過程很癢,練習把一件事的脈絡說清楚卻不落入碎念,挺難的,但總算是完成了一次還債練習,希望這個還債步伐會越踏越輕。