Git 中上下文切換的 4 種方式
所有大量使用 Git 的人都會用到某種形式的上下文切換。有時這隻會給你的工作流程增加少量的開銷,但有時,這可能是一段痛苦的經歷。
讓我們用以下這個例子來討論一些常見的上下文切換策略的優缺點:
假設你在一個名為
feature-X
的分支中工作。你剛剛發現你需要解決一個無關的問題。這不能在feature-X
分支中完成。你需要在一個新的分支feature-Y
中完成這項工作。
方案 1:暫存 + 分支
解決此問題最常見的工作流程可能如下所示:
- 停止分支
feature-X
上的工作 git stash
git checkout -b feature-Y origin/main
- 一頓鼓搗,解決
feature-Y
的問題 git checkout feature-X
或git switch -
git stash pop
- 繼續在
feature-X
中工作
優點: 這種方法的優點在於,對於簡單的更改,這是一個相當簡單的工作流程。它可以很好地工作,特別是對於小型倉庫。
缺點: 使用此工作流程時,一次只能有一個工作區。另外,根據你的倉庫的狀態,使用暫存是一個麻煩的環節。
方案 2:WIP 提交 + 分支
這個解決方案和前一個非常相似,但是它使用 WIP( 正在進行的工作 )提交而不是暫存。當你準備好切換回來,而不是彈出暫存時,git reset HEAD~1
會展開 WIP 提交,你可以自由地繼續,就像之前的方案一樣,但不會觸及暫存。
- 停止分支
feature-X
上的工作 git add -u
(僅僅添加修改和刪除的文件)git commit -m "WIP"
git checkout -b feature-Y origin/master
- 一頓鼓搗,解決
feature-Y
的問題 git checkout feature-X
或git switch -
git reset HEAD~1
優點: 對於簡單的更改,這是一個簡單的工作流,也適合於小型倉庫。你不需要使用暫存。
缺點: 任何時候都只能有一個工作區。此外,如果你或你的代碼審閱者不夠謹慎,WIP 提交可能會合併到最終產品。
使用此工作流時,你永遠不要想著將 --hard
添加到 git reset
。如果你不小心這樣做了,你應該能夠使用 git reflog
恢復提交,但是你最好完全避免這種情況發生,否則你會聽到心碎的聲音。
方案 3:克隆一個新倉庫
在這個解決方案中,不是創建新的分支,而是為每個新的功能分支創建存儲庫的新克隆。
優點: 你可以同時在多個工作區中工作。你不需要 git stash
或者是 WIP 提交。
缺點: 需要考慮倉庫的大小,因為這可能會佔用大量磁碟空間(淺層克隆可以幫助解決這種情況,但它們可能並不總是很合適。)此外,你的倉庫克隆將互不可知。因為他們不能互相追蹤,所以你必須手動追蹤你的克隆的源倉庫。如果需要 git 鉤子,則需要為每個新克隆設置它們。
方案 4:git 工作樹
要使用此解決方案,你可能需要了解 git add worktree
。如果你不熟悉 Git 中的工作樹,請不要難過。許多人多年來都對這個概念一無所知。
什麼是工作樹?
將工作樹視為倉庫中屬於項目的文件。本質上,這是一種工作區。你可能沒有意識到你已經在使用工作樹了。開始使用 Git 時,你將自動獲得第一個工作樹。
$ mkdir /tmp/foo && cd /tmp/foo
$ git init
$ git worktree list
/tmp 0000000 [master]
你可以在以上代碼看到,甚至在第一次提交前你就有了一個工作樹。接下來去嘗試再添加一個工作樹到你的項目中吧。
添加一個工作樹
想要添加一個新的工作樹你需要提供:
- 硬碟上的一個位置
- 一個分支名
- 添加哪些分支
$ git clone https://github.com/oalders/http-browserdetect.git
$ cd http-browserdetect/
$ git worktree list
/Users/olaf/http-browserdetect 90772ae [master]
$ git worktree add ~/trees/oalders/feature-X -b oalders/feature-X origin/master
$ git worktree add ~/trees/oalders/feature-Y -b oalders/feature-Y e9df3c555e96b3f1
$ git worktree list
/Users/olaf/http-browserdetect 90772ae [master]
/Users/olaf/trees/oalders/feature-X 90772ae [oalders/feature-X]
/Users/olaf/trees/oalders/feature-Y e9df3c5 [oalders/feature-Y]
與大多數其他 Git 命令一樣,你需要在倉庫路徑下使用此命令。一旦創建了工作樹,就有了隔離的工作環境。Git 倉庫會跟蹤工作樹在磁碟上的位置。如果 Git 鉤子已經在父倉庫中設置好了,那麼它們也可以在工作樹中使用。
請注意到,每個工作樹只使用父倉庫磁碟空間的一小部分。在這種情況下,工作樹需要只大約三分之一的原始磁碟空間。這這非常適合進行擴展。如果你的倉庫達到了千兆位元組的級別,你就會真正體會到工作樹對硬碟空間的節省。
$ du -sh /Users/olaf/http-browserdetect
2.9M
$ du -sh /Users/olaf/trees/oalders/feature-X
1.0M
優點: 你可以同時在多個工作區中工作。你不需要使用暫存。Git 會跟蹤所有的工作樹。你不需要設置 Git 鉤子。這也比 git clone
更快,並且可以節省網路流量,因為你可以在飛行模式下執行此操作。你還可以更高效地使用磁碟空間,而無需藉助於淺層克隆。
缺點: 這是個需要你額外學習和記憶的新東西,但是如果你能養成使用這個功能的習慣,它會給你豐厚的回報。
額外的小技巧
有很多方式可以清除工作樹,最受歡迎的方式是使用 Git 來移除工作樹:
git worktree remove /Users/olaf/trees/oalders/feature-X
如果你喜歡 RM 大法,你也可以用 rm -rf
來刪除工作樹。
rm -rf /Users/olaf/trees/oalders/feature-X
但是,如果執行此操作,則可能需要使用 git worktree prune
清理所有剩餘的文件。或者你現在可以跳過清理,這將在將來的某個時候通過 git gc
自行完成。
注意事項
如果你準備嘗試 git worktree
,請記住以下幾點:
- 刪除工作樹並不會刪除該分支。
- 可以在工作樹中切換分支。
- 你不能在多個工作樹中同時簽出同一個分支。
- 像其他命令一樣,
git worktree
需要從倉庫內運行。 - 你可以同時擁有許多工作樹。
- 要從同一個本地倉庫簽出創建工作樹,否則它們將互不可知。
git rev-parse
最後一點注意:在使用 git worktree
時,倉庫根所在的位置可能取決於上下文。幸運的是,git rev parse
可以讓你區分這兩者。
- 要查找父倉庫的根目錄,請執行以下操作:
git rev-parse --git-common-dir
- 要查找你當前所在倉庫的根目錄,請執行:
git rev-parse --show-toplevel
根據你的需要選擇最好的方法
就像很多事情一樣,TIMTOWDI( 條條大道通羅馬 )。重要的是你要找到一個適合你需要的工作流程。你的需求可能因手頭的問題而異。也許你偶爾會發現自己將 git worktree
作為版本控制工具箱中的一個方便工具。
via: https://opensource.com/article/21/4/context-switching-git
作者:Olaf Alders 選題:lujun9972 譯者:Chao-zhi 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive