HOWTO · Git
如何使用 `git reset --soft`
了解如何使用 git reset --soft 將分支移回較早的提交,同時保留暫存變更,並確認結果及安全地繼續後續工作。
本頁內容
使用 git reset --soft <target> 將目前分支頂端移至較早的提交,同時讓索引與工作目錄維持不變。因此,被移過的提交所引入的變更仍會保持暫存狀態,供你檢視後再次提交。若想合併最近幾筆提交,或修改提交訊息但保留其內容,這種做法就很實用。
git reset --soft 會變更哪些內容
軟重設會將目前分支的 HEAD 和分支頂端移至指定的提交,但不會更新暫存索引或工作目錄中的檔案。因此,舊分支頂端與目標之間的變更,會相對於新的分支頂端保持在暫存狀態。這個命令只會影響目前檢出的分支,不會移動所有指向舊提交的分支。
若要移動歷史記錄,請務必指定目標。省略目標時,Git 會使用 HEAD,因此分支不會移動。原有的暫存或未暫存工作也會保留。之後請檢視暫存差異,確認下一次提交實際包含哪些內容。
選擇要重設到的提交
使用 git log --oneline 檢視最近的歷史記錄。選擇要作為目前分支頂端的提交,並在重設前確認其摘要或雜湊值。例如,HEAD~1 表示目前提交的第一個父提交,也就是目前歷史路徑上的前一筆提交;HEAD~2 則表示沿著第一父提交往回兩步。也可以用分支名稱、標籤或提交雜湊值指定目標。
目標是要保留為分支頂端的提交,而不是要移除的提交。重設到 HEAD~1 會讓分支往回移一筆提交,並讓原先頂端提交中的變更保持在暫存狀態。如果歷史並非線性,請在日誌中確認目標,不要假設帶數字的父提交表示式一定會選到你想要的提交。
重設提交並保留暫存變更
若只要重設一筆提交,請先檢視日誌,再執行 git reset --soft HEAD~1。若要合併最近幾筆提交,請選擇適當的較早目標,例如 git reset --soft HEAD~3。索引與工作目錄都會保留,因此這些提交中的變更會一併供你建立新提交。
執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
work_dir="$(mktemp -d)"
trap 'rm -rf "$work_dir"' EXIT
cd "$work_dir"
git init -q
git config user.name "Example User"
git config user.email "example@example.com"
printf 'first version\n' > note.txt
git add note.txt
git commit -qm "Add note"
printf 'second version\n' > note.txt
git commit -qam "Update note"
git reset --soft HEAD~1
git status --short
範例成功結束,並輸出 M note.txt,表示軟重設後該變更仍處於暫存狀態。
確認暫存變更
重設後,使用 git status 確認預期的檔案已暫存。建立另一筆提交前,使用 git diff --cached 檢視實際的暫存差異。--cached 選項會比較索引與 HEAD;此時它就是選定的目標。如果顯示的變更不是你預期的內容,請先停下來檢查目標與差異,再進行提交。
暫存差異確認無誤後,使用 git commit -m "Describe the combined change" 建立替代提交。若要更新最近一筆提交,則可用 git commit --amend 取代它;確認前請仔細檢查暫存內容與提交訊息。軟重設不會自動建立新提交,也不會變更提交訊息。
--soft、--mixed 與 --hard 的差異
這三種重設模式都會將目前分支頂端移至目標,但對索引與工作目錄的處理方式不同:
git reset --soft <target>會移動分支頂端,並讓索引與工作目錄保持不變。受影響的已提交變更仍會保持在暫存狀態。git reset --mixed <target>會移動分支頂端,並更新索引以符合目標,但工作目錄中的檔案保持不變。被移過的提交所包含的變更會轉為未暫存狀態。若未指定模式,--mixed就是預設模式。git reset --hard <target>會移動分支頂端,並讓索引與已追蹤的工作目錄檔案都符合目標。目標中不存在的已追蹤編輯可能會被丟棄,因此只有在確定需要這個結果時才使用。
重設模式通常會保留無關的未追蹤檔案。不過,若未追蹤的檔案或目錄妨礙寫入目標中的已追蹤路徑,git reset --hard 可能會將其刪除。若要讓變更保持暫存狀態以建立替代提交,請選擇 --soft;若想以未暫存狀態檢視變更,請選擇 --mixed。不要用 --hard 取代軟重設。
安全使用 git reset --soft 的時機
軟重設適合用來編輯最近的本機歷史記錄,例如將幾筆提交合併成一筆,或準備將它們的變更納入另一筆提交。執行前,使用 git status 和 git log --oneline 確認目前分支與目標。執行後,在提交前檢查 git status 和 git diff --cached,避免不小心納入無關的暫存工作。
如果這些提交已經分享出去,移動分支就會改寫其他人可能已據以工作的歷史記錄。變更共享歷史前請先協調;如果要撤銷已公開的變更並保留歷史,通常使用 revert 會更合適。軟重設只會變更本機儲存庫,直到你之後推送為止,但推送改寫過的歷史可能會影響協作者。請確認目標與暫存差異清楚,並避免把強制推送當成例行的後續步驟。