在現代軟體開發流程中,版本控制系統扮演著至關重要的角色,而 Git 作為主流的版本控制系統,已被廣泛採用。在開始使用 Git 之前,建議先設定 main 作為預設分支名稱,這反映了業界的最佳實務。透過 git config --global init.defaultBranch main 指令,可以輕鬆完成全域設定。瞭解版本控制系統的演進歷史有助於理解其重要性。在 Git 出現之前,團隊協作開發需要透過手動方式傳遞和合併程式碼檔案,效率低下且容易出錯。版本控制系統的出現解決了這些問題,它能記錄所有檔案的修改歷史,方便追蹤變更、還原舊版,並支援多人同時編輯同一檔案,大幅提升了團隊協作效率。Git 不僅適用於軟體開發,也可用於其他領域,例如檔案管理、創作和教育等。它提供檔案備份、變更追蹤、版本標記、協同編輯等功能,讓使用者可以輕鬆管理不同版本的檔案,並有效地協同工作。
為何要使用 Git?
在開始使用 Git 之前,建議組態 Git 使用 main 而不是 master 作為新專案的預設分支名稱。雖然尚未討論分支的概念,但這個步驟對於瞭解 Git 的基本操作非常重要。許多軟體公司已經轉向使用 main 作為專案穩定程式碼函式庫的預設分支名稱。在實際應用中,你會看到這兩個名詞都在使用(甚至在這本文中也會出現),但如果你希望新專案使用 main,可以執行以下命令:
$ git config --global init.defaultBranch main
完成所有技術準備後,我們就可以開始了!
Git 的優勢
瞭解在自動化工具如 GitLab CI/CD 管道出現之前,我們是如何建構軟體的(如第 1 章所討論的),對於理解開發團隊如何協調編輯同一組檔案的過程非常有幫助。這些工具旨在解決開發者面臨的許多問題,但讓我們只看其中一個問題。假設你和你的夥伴 Elizabeth 一起在同一個程式碼函式庫上工作,並且你們都想編輯同一些檔案。再進一步想象一下,這是 Git 或其他版本控制系統(VCS)出現之前的時代。在那個時代,唯一的寫程式方式是你編輯一個檔案,然後透過電子郵件、分享網路磁碟或可攜式磁碟傳遞給 Elizabeth。然後,你必須告訴她可以開始編輯了。她會以某種方式取得檔案(例如在試算表中加入一條她擁有檔案控制權的紀錄),並且在她需要的時間內保持對檔案的控制權。如果你有新的想法並想再次編輯這個檔案,你需要請她停止編輯並將檔案轉回給你。當她轉回來時,你需要逐行檢查整個檔案以瞭解她做了哪些變更,並希望這些變更不會與你想要做的變更衝突。然後,你們需要對每個檔案重複這個過程,每當任何人想要編輯這些檔案時。你可以想像這個過程有多慢且繁瑣,以及在所有權轉移過程中有多少機會出錯!
瞭解了舊時代的操作方式後,我們可以來看看什麼是 VCS、它如何解決這些問題以及它如何使開發者的生活更輕鬆。
版本控制系統(VCS)是什麼?
VCS 是一種設計來使一個或多個開發者更容易與一組檔案一起工作的工具。它透過製作專案中所有檔案在特定時間點的快照來實作這一目標,並允許你檢視、比較和還原不同快照中的檔案。
基本 Git 指令練習
每個 VCS 的功能稍有不同,但大多數都提供以下功能:
- 提供檔案備份,以防當前版本丟失或被意外覆寫。
- 顯示檔案內容隨時間變化。
- 顯示誰對哪些檔案進行了哪些變更以及何時進行。
- 為未來參考標記某些特定快照。
- 提供每組變更的人類可讀描述,以便團隊成員瞭解為什麼進行了變更。
- 允許開發者以與其他開發者同時編輯相同檔案相容的方式編輯檔案。
多年來已有許多競爭VCS, 包括開源和專有版本。其中一些最著名的例子包括 Microsoft Visual SourceSafe、CVS、Apache Subversion 和現在的 Git。我們稍後會解釋為什麼Git主要佔據了VCS空間併為任何沒有公司命令使用Git競爭對手的團隊服務作為預設VCS.換句話說,Git贏得了VCS競爭,因為它使開發人員能夠管理軟體專案中的任何檔案。
例如,你可以使用相同VCS管理Java,Python和Ruby專案中的檔案.雖然我們通常認為VCS是幫助您與電腦語言中的原始碼檔案合作,但它們可以與軟體專案中的任何檔案一起使用,包括(但不限於)以下內容:
- 檔案,例如Markdown或PDF檔案
- 組態,例如JSON或YAML檔案
- 測試程式碼和資料
- 整合開發環境(IDE)元資料或組態資訊
- 其他專案資產,例如圖片、影片或聲音檔案
無需將VCS限制於僅軟體專案!您可以使用Git或任何VCS管理詩歌集中的詩歌、食譜集中的食譜或小說中的章節.VCS適用於涉及電腦上的任何專案!
VCS解決什麼問題?
現在瞭解 VCS 如 Git 提供哪些功能後,你可能會想到 VCS 能解決軟體開發者面臨的一些日常問題。以下只是一些情境,但你肯定能想到更多。
常見問題解答
問題1: 落實分支策略
在選擇使用 main 作為預設分支時,為什麼不直接使用 master?
答案:隨著社群對語言和術語敏感度提升,「master」一詞可能帶有一些不適當含義。「main」作為替代方案不僅符合現代社交語言規範還能確保團隊對專業用詞保持專注。
內容解密:
$ git config --global init.defaultBranch main
此指令可全域設定新專案之預設分支名稱為 main。
- 全域設定:此指令將作用於所有新建立之專案。
- 預設分支:其設定主要影響於初始化新專案時之預設分支名稱。
問題2: VCS 的基本概念與應用
除了軟體開發外還有哪些情境適用 VCS? 答案:除了軟體開發外,「VCS」也可應用於創作、教育以及各式資料管理等領域。
- 創作領域:如詩歌集管理、食譜集整理以及小說寫作等。
- 教育領域:如教學材料更新維護以及學生作業版本管理等。
- 資料管理:如資料函式庫迭代更新及備份等。
內容解密:
無論是寫作還是教育領域都能透過「版本控制系統」來追蹤變動歷史。
- 追蹤歷史:所有修改內容均可追蹤到每次修改細節。
- 協同工作:多人合作時便於協同工作與版本合併。
問題3: VCS 在軟體開發中的優勢
假設沒有 VCS 的支援下如何進行軟體開發? 答案:早期沒有 VCS 前期團隊協作往往依賴手動方式傳遞修改後之檔案進行合併更新處理。
內容解密:
- 傳遞方式:常見之方法包含電子郵件、分享網路磁碟或可攜式磁碟傳遞進行更新合併。
- 合併挑戰:每次修改需要手動比對合併確保不會產生衝突。
此圖示展示了傳統軟體開發與現代 VCS 工具間之差異化運作模式:
分析:此圖示呈現傳統流程與現代化工具之比較:
- 傳統流程: 傳統軟體開發依賴手動方式進行傳遞與比對處理。
- 現代化工具: 自動化流程進行資料處理並自動進行比對處理。
## Git 的強大之處
Git 是一種分散式版本控制系統(VCS),廣泛應用於軟體開發中。它能夠幫助開發者追蹤程式碼變更、協同工作,並且提供了豐富的功能來管理程式碼的歷史版本。以下是一些使用 Git 的主要原因及其優勢。
### 為什麼要使用 Git?
#### 瞭解程式碼變更的原因
開發者可能會在某天早上開啟原始碼,發現某些方法的演算法完全改變了。這時候,Git 的提交訊息(commit message)就能夠幫助你瞭解這些變更的原因。雖然一些提交訊息可能不夠完整,但大多數情況下,你仍然可以瞭解變更的動機。例如,新演算法是否比舊演算法更快?新的程式碼是否更短或更易讀?
#### 追蹤程式碼變更的時間
假設你幾個月沒有檢視某個 Java 類別,發現它有新功能加入或舊功能移除。這時候,Git 的提交紀錄(commit log)能夠告訴你這些變更何時發生,以及它們是否在最後一次佈署到生產環境之前發生。這樣你就能夠確定客戶目前使用的是哪個版本的類別。
#### 追蹤錯誤程式碼的來源
Git 提供了一個稱為「blame」的功能,它能夠告訴你哪位開發者編輯了某行程式碼。當你發現某段新加入的程式碼有錯誤或效能問題時,這個功能非常有用,因為你可以找到具體的人來修復它。此外,「blame」功能也有積極的用途:當你發現某段特別巧妙的程式碼時,你可以知道該向誰學習。
#### 還原遺失的檔案
Git 能夠幫助你輕鬆還原遺失的檔案。即使你不小心刪除了檔案,只要你使用 Git 管理過該檔案,Git 都能夠幫助你還原到最後一個版本。
#### 還原特定目錄或檔案的歷史版本
你不僅可以還原單一檔案的最後版本,還可以還原任何歷史版本的檔案。例如,如果你花了幾個小時重寫自動化測試以使其執行得更快,但發現新測試要麼更慢要麼無法正常運作,Git 允許你替換單一檔案、整個目錄或整個專案中的所有檔案。只要你定期將變更提交到 Git 中,就不用擔心失去工作或回復到舊程式碼。
### 基本 Git 指令操作
#### 跨人協同編輯同一檔案
VCS 最常用的功能之一是它能夠安全地分割不同開發者對同一檔案的編輯,以避免彼此覆寫對方的工作。每位開發者都有一個自己的分支(branch),可以在其中編輯任何檔案。當每位開發者完成工作後,他們會將自己的分支合併(merge)到專案的穩定程式碼函式庫中。這樣多位開發者可以同時編輯同一檔案而不會丟失任何工作或需要協調檔案擁有權。
#### 佈署特定版本的程式碼
VCS 允許你標記特定版本的檔案,以便輕鬆檢視或還原那些版本。例如,在進行重大重構專案之前標記整個程式碼函式庫,以便如果重構失敗時可以輕鬆回復到已知好的狀態。更常見的是,開發團隊通常會標記特定版本的程式碼,以便知道哪些程式碼已經與特定釋出一起佈署。例如,當有人報告某個版本中的錯誤時,你知道應該檢查哪個版本的檔案來進行排錯。
#### 分享編輯後的程式碼
當你編輯一個檔案後,團隊成員必須知道這些編輯並能夠看到這些變更。VCS 使得推播(push)編輯到中央位置非常容易。然後其他團隊成員可以提取(pull)這些變更到他們的本地電腦上,保持整個團隊同步。
### Git 為何流行
Git 已經成為主流 VCS 的原因有很多。以下是一些主要特性和原因:
#### 出身背景
Git 是由 Linus Torvalds 為了管理 Linux 作業系統核心原始碼而建立的工具。由於 Git 原來用於儲存高知名度、成功且廣泛採用的 Linux 核心程式碼,因此自然獲得了即時評價和影響力:如果它足夠穩健和可靠到 Linus 和 Linux 的需求程度,那麼對於其他人來說也就足夠好了。
#### 分支管理簡單
如同稍後將學到的那樣,「分支」是任何 VCS 中最重要的一部分之一。Git 是從一開始就設計得簡單易用來建立、使用和合併分支。分支管理上的便利性無疑是其成功的一大原因。
##### 單行註解:
```plantuml
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Git 版本控制入門:優勢、指令與實務應用
package "Git 版本控制" {
package "工作區域" {
component [工作目錄
Working Directory] as work
component [暫存區
Staging Area] as stage
component [本地倉庫
Local Repository] as local
component [遠端倉庫
Remote Repository] as remote
}
package "基本操作" {
component [git add] as add
component [git commit] as commit
component [git push] as push
component [git pull] as pull
}
package "分支管理" {
component [git branch] as branch
component [git merge] as merge
component [git rebase] as rebase
}
}
work --> add : 加入暫存
add --> stage : 暫存變更
stage --> commit : 提交變更
commit --> local : 版本記錄
local --> push : 推送遠端
remote --> pull : 拉取更新
branch --> merge : 合併分支
note right of stage
git status 查看狀態
git diff 比較差異
end note
@enduml
此圖示展示了 Git 在管理原始碼中的主要操作流程:從提交變更開始、追蹤歷史記錄、還原舊版和協同合作等。
# 單行註解範例
print("Hello, World!")
小段落標題
內容解密:
- 上述範例展示了一段簡單且典型 Python 的單行註解。
print("Hello, World!")函式會在控制檯輸出Hello, World!。- 此範例說明瞭如何在 Python 中新增單行註解並使用
print函式執行輸出操作。 - 注意
print函式需要括號內放置字串字面值。 - Python 應用廣泛且語法簡潔易懂。
- 論語法之外還需瞭解各種函式與模組。
- 在專案中適當新增註解非常重要以便後續維護與理解。
# 基本 git 指令範例
def commit_message():
return "更新了某個功能"
def revert_version():
return "回復到上次版本"
小段落標題
內容解密:
- 根據 Python 的基本 git 指令範例展示如何管理提交訊息與回復版本。
commit_message()函式傳回更新功能相關訊息。revert_version()函式傳回回復至上次版本相關訊息。- 應用範圍包含日常開發與專案管理。
- 根據以上簡單概念進一步理解 VCS 工具及其重要性。
- 提升專案之維護性及協同效率。
- 在實務上適當利用 VCS 來增強團隊協作與流程管理。
- 在進行迭代更新前建立新分支以保持主分支穩定性。
# 分支管理範例
def create_branch(branch_name):
return f"建立新分支: {branch_name}"
def merge_branch(target_branch, source_branch):
return f"合併 {source_branch} 分支到 {target_branch}"
小段落標題
內容解密:
- 分支管理範例展示如何建立及合併分支。
create_branch(branch_name)函式傳回新分支建立訊息。merge_branch(target_branch, source_branch)函式傳回合併兩分支訊息。- 分支設計考量確保各階段工作獨立進行而不影響其他人之工作進度。
- 在實際專案中經常使用分支來進行特性開發及修正 Bug。
- 分支合併時需注意處理衝突及測試以確保系統穩定性。
- 適當利用分支進行專案管理有助於提升開發效率及降低風險。
- 需針對每個階段規劃好分支策略以達最佳效果與穩定性。
# 版本標籤範例
def tag_version(version_name):
return f"標記版本: {version_name}"
小段落標題
內容解密:
- 標籤版本範例展示如何對特定版本進行標記。
tag_version(version_name)函式傳回特定版本標記訊息。- 標籤設計考量確保每次釋出都有一致且清晰之歷史紀錄可供追溯。
- 在實際專案中經常使用標籤來區分不同釋出之間區別及跟蹤問題根源。
- 標籤具有唯一性並且不可修改以保證歷史紀錄準確性及完整性。
- 每次釋出前應確認所有功能測試透過並進行標記操作以確保系統安全性及穩定性。
# 整合團隊協作之 git 推播與提取指令範例
def push_changes():
return "推播變更至遠端倉函式庫"
def pull_changes():
return "從遠端倉函式庫提取最新變更"
小段落標題
內容解密:
- 推播與提取指令範例展示如何將地端倉函式庫變更整合至遠端並更新最新狀態至地端。
push_changes()函式傳回推播至遠端倉函式庫之訊息表示提交變更成功。pull_changes()函式傳回從遠端倉函式庫提取最新變更之訊息表示更新成功。- 推播與提取設計考量確保團隊成員間可分享資源及維持資料同步性。
- 在實際專案中經常使用推播與提取指令進行團隊協作及資料更新等操作.
- 推播前應確認所有檔案已提交並沒有衝突存在才進行操作以保證資料完整性.
- 提取前應先將地端尚未提交之檔案暫存起來才進行更新避免丟失資料.
- 在多人共同編輯同一檔案時需注意及時推播與提取以避免衝突問題.