最近在和同事協同開發的時候,發生了一件事情:
  由於我們還沒啟用CD(自動部署)但是更新測試機器又不一定是同一個人,為了好管控目前程式碼和目前測試機器上面的版本,我們使用了一個標籤叫做TestServer來記錄。   
  不過當我同事更新的時候,他使用了testserver作為標籤,結果我這邊發生了雖然local只有一個tagtestserver,但是在remote上面其實有兩個標籤:TestServer和testserver。   
為什麼會發生這個事情呢?如果不處理,未來在看的時候非常混亂,這讓我想起來一直想要寫的一篇文章,為git repo、tag和branch取名的時候應該要注意什麼比較不會有問題,因此兩篇一起寫,算是不好好naming會帶來什麼問題的use case範例。
搜索關鍵字:naming guidance for git repo, tag and branch.
解決方式 - TL;DR
如果remote出現了兩個一樣名字的標點,但是只是大小寫不同,那麼:
- 建議保留小寫的版本
-      用以下指令刪掉遠端有大寫的標籤     git push --delete {tagName}例如: git push --delete TestServer
取名建議 - TL;DR
基本上對於取名,不管是repo、branch還是tag的時候,建議:
- 全部使用小寫
- 由於習慣寫.net code,因此很習慣會用Pascal Casing來取名,例如 - UnReleased。但是,由於repo、branch和tag都屬於url的一部分,而url理論上是會區分大小寫並且 作業系統檔名是否區分大小寫處理也不同(windows不區分,Linux會區分),因此為了抓下來不會有問題,建議全部使用小寫。因此應該使用- unreleased。- 可是如果字太長要區分怎麼辦?參考下面分割字符 關於url應該區分大小寫,可以參考W3的HTML and URLS裡面提到:- Users should always consider that URLs are case-sensitive。
-      使用-(aka 減號、dash)作為文字切割
- 如果名字太長想要切割的話,可以使用 - -來區別,例如:- my-name-is。- 有些會習慣使用 - _(下底線)。- 使用 - -有幾個好處:- 輸入-不用加shift - 比較好輸入
- -在regex不屬於- word而- _屬於,因此用來切割符號比較明顯
 - 當然有時候字太長了,所以會混合用。 
- 輸入
-      用/(斜線)來分類branch和tag
-      如果有在用git flow應該會很習慣,主要是用/(斜線)在工具像小烏龜可以簡單找到相關內容。好區分範例 - 兩個feature,A和B 
-      tag使用v做前戳,搭配SemVar
-      舉例來說,v1.0.1。加v的好處是如果要列出和版號有關的tag,可以先打v然後在按下tab
當然,上面都只是建議,沒有對錯,只是習慣或者避免一些小問題。
上面有些建議裡面已經有包含說明,如果對於一開始提到的問題發生原因有興趣的話,繼續往下看.....
重現問題
首先我們先來重現一下問題(這個重現方式和我實際發生的情境有點不同,因為我的情境需要兩個帳號交叉才看得到,不過local可以用以下方式重現,問題點是一樣)。
接下來,我們要:
- 建立一個repo
- 先打一個UnReleased的標籤
- push到remote
- 修改在打一個unreleased的標籤
- push到remote
- 檢查
建立一個repo
可以參考另外一篇該怎麼開專案的資料夾結構?每個專案應該要有的資料夾結構和檔案的Powershell語法來建立一個repo:
git clone https://github.com/alantsai/mhat-common-boilerplate-repo.git cd mhat-common-boilerplate-repo rm .git -Recurse -Force git init git add -A git commit -m "init project"
這個時候,我們修改其中一些檔案。
先打一個UnReleased的標籤
   做完修改commit之後我們打一個UnReleased的tag    
push到remote
在修改之後打一個unreleased的標籤
   注意這邊的大小寫應該是都小寫的unreleased。    
檢查
   發現到,在本機只剩下全小寫的那個unreleased的標籤,有大寫的不見了,但是在remote,大小寫兩個標籤都在。    
了解為什麼local變成一個而remote還是兩個
要了解這個發生的原因我們需要兩個前置的訊息:
- git tag是怎麼儲存
- 作業系統對待檔名大小寫的不同
git tag是怎麼儲存
   git的資訊其實是存在.git\refs\tags裡面(好吧,這個說法其實不太精準,以下會在說明),以我這邊為例,可以看到有一個叫做unreleased的檔案,這個檔案的內容其實存的是一個hash值指向tag的位置。    
了解這個之後搭配下面的資訊我們就知道為什麼了。
作業系統對待檔名大小寫的不同
Windows和Linux在處理很多事情上面其實不太一樣,這裡面有一個不同之處在於如何對待檔名大小寫:
- Windows不區分大小寫
- Linux區分大小寫
   什麼意思呢?舉例來說,如果我有兩個檔案,一個叫做UnReleased另外一個叫做released:    
- 在Windows,兩個檔案會互蓋,換句話說,在同一個資料夾,這兩個檔案只能留1個
- 在Linux,因為區分大小寫,因此在同一個資料夾兩個檔案可以共存,換句話說不會互蓋
   搭配上面的資訊,為什麼變成一個的原因就浮出水面了,當第一個tag建立的時候,會有個檔案叫做UnReleased出現,當第二個tag unreleased出現的時候,因為Windows不區分大小寫,直接就把    UnReleased蓋掉了,因此local變成只有一個。    
那remote為什麼還是兩個呢?因為我們push上去的地方時github,那github host在linux(應該是啦,這個我沒找到Reference,所以說錯和我說一下,不過大部分的host應該都是liunx),而linux 區分大小寫,所以保留了下來。
結語
其實這一篇混雜了兩個主題:
- 建議的naming方式
- 如何解決因為naming問題導致出現兩個標籤的問題
由於兩個主題有相關因此寫在了一起,算是為了建議naming的一個use case範例。
不過就像上面說的,這邊的是建議而不是一定要這麼做 - 也是結合了網路上大家的建議,當然大家有不同的想法,因此不一定都認同,也希望提出不同意見讓整個資訊更加豐富。
在追蹤問題的時候,會發現其實需要一些git和OS之間差異的資訊才有辦法發現實際的問題 - 告訴我們 學無止境阿.....
 
沒有留言 :
張貼留言