git worktree 簡單介紹與使用

現在可以在同一個專案之中,一次開啟多個不同的 branch 了。

Ray Yuan Liou
7 min readMar 31, 2019
標題說的是真的嗎?

近日在推特上看到這篇推文:

發現了很多以前不知道的 git 功能,這次引起我注意的除了 git rerere 以外,還有 git worktree 這個指令。我因為好奇研究了一番,發現這個指令可以適用於以下的情境:
在開發途中,時常需要切到其他 branch,無論是需要對照、修 bug 或是開發一個插單的新功能。類似這種情形,我常常會 git stash 目前的更動,待處理完其他事情回來再 git stash apply (或是先 commit 變更,待其他的 Task 處理完回來後再 git reset)。

git 2.5 之後新增了 git worktree ,就可以減少 branch 切來切去的各種麻煩。這裡的 worktree 指的是 Working Tree (工作目錄),其實,在某個資料夾裡進行 git init 或是 clone 一個遠端的專案下來,這個資料夾就會變成一個工作目錄。(即是由 git 管理的專案資料夾)
git worktree 這個指令可以為同一個專案製造多個工作目錄,並且其他目錄的變更經 commit 後,會回到原工作目錄。

遇到需要警急上 patch 修 bug,但又不想 git stash 掉目前的開發進度。現在可以新增新的工作目錄另外處理,不影響到目前的開發狀況。

範例

以我手邊的 Android Codelab 教學專案為例,現在的狀況是我更動到一半:

現在需要回 master branch 改東西,想像成是修 bug 打 patch 之類的。
在說明 git worktree 指令之前,我先補充說明我的幾個習慣作法:

  1. (1) 先 git stash 後回到 master branch
    (2) 在 master branch 開一個新的 branch
    (3) 這個 branch 處理完之後回到原 branch
    (4) 考慮到可能在其他地方也做了 git stash 所以用 git stash list 來查是哪一個 stash 是上次離開前的狀態
    (5) 記下 index ,下 git stash apply “stash@{index}” 回朔之前的工作狀態
  2. (1) 先加入所有變更到 stage,Commit 一個 [WIP] Commit 後回到 master branch
    (2) 在 master branch 開一個新的 branch
    (3) 這個 branch 處理完之後回到原 branch
    (4) 查看 git log 看 [WIP] Commit 的上一個 Commit Hash 值
    (5) 下 git reset <Hash> 回到上次離開前的狀態

因為不管哪個 branch 都是共用同一個工作目錄,需要處理其他 branch 的話,正在處理中的就需要透過某種方式讓位,像台鐵臨時停車。

git worktree 指令可以讓你不用離開目前的工作階段,在其他的資料夾新增另一個工作目錄,在那裡進行變更。就像是多了幾條軌道,不用誰讓位就可以繼續前進。

$ git worktree add -b <new_branch_name> <folder_path> <source_branch>

你可透過上述的指令新建工作目錄,git 會 clone <source_branch><folder_path> 資料夾,這個新 branch 會叫做 <new_branch_name>

範例中透過指令

$ git worktree add -b enhancement/gradle_upgrade ../gradle_update master

新增一個基於 master 的新 branch,這個 branch 叫 enhancement/gradle_upgrade,位於 <上層目錄>/gradle_update 資料夾,是全新的一個工作目錄。

另外,你可以透過指令

$ git worktree list

來查看目前有幾個工作目錄。

接著,切換到新的工作目錄 ,也就是前往新建立的資料夾,看看是否是基於 master branch,是否乾淨。

是乾淨的!

看起來一切準備就緒,可以用編輯器開啟這個資料夾,進行想要的操作。而且,現在可以同時編輯多個工作目錄,不會受限於單一個 branch。

接著就跟往常一樣作業,處理好後別忘了 Commit 變更。
Commit 後就能把這個資料夾刪掉了。對,就能把這個資料夾刪掉了。
因為這些變更在 Commit 後已經回到了主工作目錄。

最後,別忘了下

$ git worktree prune

因為在進行 prune 之前,我們沒辦法從主工作目錄切換至這個藉由 git worktree add -b 指令建立的 branch。git 會說他已經 check out 到其他的資料夾了,你自己前往那個資料夾存取。

prune 這個指令,會將其他的工作目錄與主要工作目錄斷開魂結。下完指令後,被移除資料夾的工作目錄會在 git worktree list 列表之中消失。同時,主要工作目錄也能自由切換至該 branch。

如果不進行 prune,git 每三個月會自動整理一次工作目錄。所以最終被刪除資料夾的工作目錄還是會和主工作目錄撇清關係。

其他狀況

不想新建 branch,只想爲已有的 branch 建立新的工作目錄。
這種情況,可以這樣子新建:

$ git worktree add <folder_path> <source_branch>

這樣不會建立新的 branch,而是把已有的 branch 移至其他的工作目錄下。其他的操作方式,與上述相同,就不再重複。

結論

整理這篇用到的相關指令:

查看目前工作目錄
> $ git worktree list
新建工作目錄
作為全新 branch
> $ git worktree add -b <new_branch_name> <folder_path> <source_branch>

從已有的 branch
> $ git worktree add <folder_path> <source_branch>
重新整理工作目錄
> $ git worktree prune

參考資訊:

如果你喜歡這篇的文章,可以訂閱這個 Medium 帳號。
我會不定期更新一些技術分享。 (👈🏼 這句話就是個 MOU 📝,你懂的)

--

--