# 前言

今天的主題是最近跟一個朋友討論 Git 時,他提出跟我所理解的 Commit 不同的觀點,筆者認為很有意思。

原本打算把這個議題紀錄在上一篇文章的「常見問題」,不過內容打完之後,發現 廢話太多 內容太長,想要刪減內容卻發現無法一言以蔽之,決定還是獨立成一篇文章。

絕對沒有要水一天的意思!!

先說這個問題的答案:因人而異、因專案而異。

# 每個 commit 都應該是一個完成品才對吧?

朋友提出了一般聽到發佈「版本」、發佈「新版」時會意識到的事情,這個用詞大多是會出現於「已經可以使用的產物」上。

例如:

  1. 工程師寫好的第一版程式
  2. Windows 發佈的安全性版本
  3. 蘋果發佈了新版的 iPhone 但我買不起

他不理解為什麼第一個 Commit 可以只有一個 readme.md 說明檔,或者只有一些基本設定。
認為只要是 Commit,就該像上面說的那樣,要是個「成品」,應該要是「開發好」的東西,當然 第一次的 Commit 也必須是這樣才對。

但實務上… 每一件作品都有辦法在短時間內完成嗎?

# 實務上使用 Git 的「版本」概念

版控的類別一文中曾經聊到「版控」這個詞彙的意義,當時有提到它跟「遊戲存檔點」是一樣的概念,能讓我們能在進攻下一個 Boss 不小心失敗時,不用「從零開始」闖關。

我們「開發過程」的每一次 Commit 都是這個道理,保存已完成的重要內容,避免後續操作不小心改壞,而前功盡棄。

無論你是設計師也好,是工程師也好,甚至你還只是個學生,應該都有需要完成一個作品的經驗。

設計師趕稿子、工程師趕程式、學生趕論文 (幫 QQ)

這些行為所歷經的過程,並不單單只有「開始」、「結束」而已,雖然我們總是會記得把「完成」的作品進行備份,不過除了「完成」的內容外,版控更重要的動作是去把「關鍵時間點」存起來。

舉例來說:

  • 設計師要規劃出整個網頁,當稿子處理到一半,但已經到了下班時間。
  • 網頁工程師開發網頁,預計要切版外加寫 code 才能完成,而在切完版時已經差不多要下班了。
  • 學生要趕論文,寫了一整天,終於寫完了第一章,看看時間已經凌晨一點, 該吃消夜了

請問上述這些例子,是不是都算是「關鍵時間點」?

雖然這些狀況都沒把作品做完,不過總是希望有個機制先把完成的部分記錄起來,避免後續發生什麼意外,造成無法挽回的局面。

如同遊戲闖關,我們好不容易玩到某一個段落,這些辛苦的過程如果不好好存起來,要再叫我從頭來過,我真的會直接翻臉!
人家不玩了

實務上就算我們還沒完成作品,也會先 commit 已完成的部分。

# 我能不能全都要?

我相信在座的各位,都是大人了。
選擇是小孩才會做的事情,身為大人的我們,可以正大光明的說:
我全都要.jpg

關鍵時間點確實是在「開發過程」很重要的版本依據,不過每個完成品也都會是辛苦已久的重要結晶。
如果把「關鍵時間點」跟「完成品」混合在一起,在追溯時可能會導致一定程度的困難。 不對,應該是真的很困難

Git 有一個很重要的功能名叫「分支」,就有辦法做到讓「關鍵時間點」是一個脈絡,「完成品」又是另一個脈絡。

再把這張圖請出來用,這次請把目光看到左邊的樹狀圖;
樹狀圖示意

如果你是第一次接觸 Git 的讀者,一時之間想不通這些線跟工作目錄之間的關聯,也先不用著急,分支的操作方式以及使用觀念,之後都還會再說明,現階段我們直接看圖說故事就好。

你可以先想像這是遊戲進度條 (人人應該都有玩過遊戲的,對吧?),從右往左數的四條線都是「支線任務」,最左邊的「藍色線」是「主線任務」,要讓主線任務出現的條件,是要先破完支線任務,才會開啟專屬於每個支線的主線任務。

支線任務上有好幾個 點點,就是任務的闖關點,這四個任務不用同時進行,彼此之間也不會有任何干擾因素。

如果已經先完成 粉色 任務後,不一定要馬上打粉色的主線任務,可以再把 綠色橘黃色紫色 支線任務都打完再說。

即使支線任務都完成了,也不用依照完成順序去打主線任務,可以依照心情選擇主線。

以上圖的例子來說,玩家 (?) 一開始先打完三場 橘色,又打一場 粉色 ,後來又打一場 橘色
專案起初示意

最後的完成順序,是 粉色 => 橘色 => 綠色 => 紫色,並且先開啟 橘色 的主線任務,再來是 綠色粉色紫色 則還沒進入主線任務。
專案收尾圖

說完故事後,我們再回來 Git 的世界。 不要念念不忘遊戲世界,給我回來!

每條支線都是在記錄不同開發人員的「關鍵時間點」,而主線就是專門用來收割 (?) 支線「開發完成」的內容。

用這種方式來管理一個專案,就能同時做到保留「關鍵時間點」,也讓「完成品」獨立在一條主線上,這也是分支會被稱為 Git 版控主要功能的原因之一。

還沒分岔任何支線的第一個 commit ,大家也可以想成玩遊戲時,辦好遊戲帳號、輸入好玩家姓名之後,總是會有「新手教學」的階段,必須等到這個階段跑完才能真正開始遊戲,那些主線任務、支線任務的起始點,都會以這個階段為基礎開始進行。

回到最初的那個問題吧:

# 第一次的 commit 該存什麼內容?

這是建仁與建志這兩個人之間的問題

重點在於專案第一個「關鍵時間點」是什麼?

有使用框架的開發人員,剛做好專案的架構,就可以先將架構紀錄到儲存庫。

如果沒有什麼架構內容想記錄,也有人會先丟一個 readme.md 的說明文件,像是在 GitHub 建立遠端儲存庫,就有這樣的選項。
GitHub 說明檔案示意圖

假使上面提到的狀況都不符合你的情境,也可以依照自己的情境來決定第一次 commit 要放的內容,完全是沒有問題的。

Git 只是個工具,該怎麼使用是我們要自己決定的,Git 不會規定我們該如何使用他。

# 朋友在聽我說完後,講述他的理解

Git 的歷程,就像是一棵小樹苗慢慢茁壯成大樹一般,需要長出一節一節的節點,而每個 Commit 都是這棵樹重要的節點。

所謂第一個 Commit,是這棵大樹最一開始的節點,更準確地說,他是這棵大樹「最初的種子」。

我們需要有這顆種子,才能使其繼續發芽,所以在專案的起初,我們就需要定義好,這顆種子應該要是什麼模樣。