開發中你不得不知的一個Git小技巧
一. 背景
在工作中大家應會碰到需要頻繁在兩個分支中切換工作的情況,我們通常做法是利用git stash命令暫存當前工作區中的變更,然后git checkout到目標分支中工作,工作完成后回到剛剛分支使用git stash pop命令還原歷史工作區變動。
整體流程大致如下:
# 當前工作分支,存在變更
$ worktree-test (dev1) git status
On branch test
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: bbb.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 暫存變更
$ worktree-test (dev1) git stash
Saved working directory and index state WIP on test: 2bc59f3 add bbb.txt
# 切換分支
$ worktree-test (dev1) git checkout dev2
#........在dev2上進行代碼修改并提交
# 切換回原先的dev1分支
$ worktree-test (dev2) git checkout dev1
# 還原工作區變更,繼續開發
$ worktree-test (dev1) git stash pop
On branch test
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: bbb.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (3890bfc0568be86c8ba2a26c7138966bf8776e5c)
上述流程如果在我們需要反復多次在兩個分支間切換工作的時候會很不方便,因為你每一次checkout都會使得IDEA重建索引,如果在項目比較大的情況下會非常耗時。
此時有很多小伙伴可能會選擇重新clone一份代碼下來,在兩個本地倉庫中并行開發,這么做固然可以解決問題,但是Git官方給出了更優雅的解決方案,那就是git worktree。
二. 什么是worktree
Git worktree嚴格意義上說已經不是一個新的功能了,它推出也已經好幾年了,是在2015年7月發布的2.5版引入的。worktree是鏈接到統一倉庫的多個工作區(目錄,樹)。一個git倉庫可以支持多個工作樹,分別對應不同的分支。我們在git中通過git init或git clone創建一個(主)工作區(樹)(main working tree)。
同理,我們使用 git worktree 創建一個(和工作區)不同目錄的工作區(樹),我們稱之為為"鏈接工作區(樹)(linked working tree)"。git倉庫有一個主工作樹(裸庫)和零個或多個鏈接工作樹。與重建的孤立的目錄不同,鏈接工作樹和主倉庫直接就行分支一樣是有機關聯的,任何一個鏈接工作樹的變更提交都在倉庫內部。鏈接工作樹用完后,可以直接通過git worktree remove刪除。

三. 基本使用

我們當前工作區處在test分支上,假設我們需要在test和dev兩個分支間來回切換,此時我們可以創建一個worktree并行去開發:
$ worktree-test (test) git worktree add ../worktree-test-dev dev
Preparing worktree (checking out 'dev')
HEAD is now at 7e8e244 add aaa.txt
此時Git就會在我們指定的目錄(../worktree-test-dev)中創建一個新的worktree,

這樣我們就能將worktree-test-dev這個文件夾導入IDEA,這樣就能在不切換分支的情況下,在兩個分支下并行開發,這樣就能節約頻繁分支切換導致的效率問題。
不同的worktree之間共用同一個 commit 樹,這樣我們在 worktree-test-dev 文件夾做變更并提交后,commit信息也會在別的 worktree 的commit tree中看到。
當我們在臨時創建的 worktree 中完成工作后,我們可以通過 git worktree remove 刪除這個 worktree:
# 查看當前有哪些worktree
$ worktree-test (test) git worktree list
C:/Users/JindongTian/Desktop/worktree-test 2bc59f3 [test]
C:/Users/JindongTian/Desktop/worktree-test-dev 7e8e244 [dev]
# 刪除臨時創建的 worktree-test-dev worktree
$ worktree-test (test) git worktree remove ../worktree-test-dev/
執行完成后,我們就能發現worktree-test-dev文件夾被刪除,而剛剛在worktree-test-dev的提交,仍然保留在 commit 樹中。
四. 常用命令
4.1 新建worktree
git worktree add <新路徑> <分支/commit ID>
需要注意的是,使用 git worktree 創建的多個目錄,不能有任何兩個目錄在同一個分支下,這樣是防止兩個文件夾在相同的分支下做不同的修改。所以我們在創建worktree時,<分支>一定是不能是當前分支。如果我們想基于當前分支創建一個新分支,并創建基于新分支的worktree可以這樣做:
git worktree add -b <新分支名> <新路徑> <分支/commit ID>
4.2 查看 worktree 列表
git worktree list
4.3 刪除 worktree
git worktree remove <路徑>
需要注意的是:
-
該命令只能刪除干凈的工作樹(沒有未跟蹤的文件,也沒有對已跟蹤文件進行修改但未提交的情況稱為干凈的工作樹)。不干凈的工作樹或帶有子模塊的樹需要使用–force刪除。
-
主工作樹無法刪除。
4.4 清理worktree的配置信息
git worktree prune
清理worktree的配置信息 $GIT_DIR/worktrees。例如手動刪除了一個worktree的文件夾但是沒有執行git worktree remove,git并不能識別出已經刪除了。此時就可以使用git worktree prune手動更新項目的woktree配置。
4.5 移動 worktree 目錄
git worktree move <原路徑> <新路徑>
將working tree目錄移動到新位置。主目錄和帶有子模塊(submodules)的目錄不可以移動。

浙公網安備 33010602011771號