cover

reset --hard 按下去的那一刻你會怕,但學完 reflog 你就不怕了。

先講結論

這篇講的是 Git 的「後悔藥」和「急救包」:版本回退讓你反悔、stash 讓你暫停手邊工作、cherry-pick 讓你精準搬運 commit、reflog 在你搞砸一切時救你一命。搭配 上篇的分支管理 一起服用。

reset 三兄弟:搞懂差別很重要

git reset --soft HEAD^     # 只回退 commit,暫存區和工作目錄都還在
git reset --mixed HEAD^    # 回退 commit + 暫存區,工作目錄還在(預設)
git reset --hard HEAD^     # 全部回退,什麼都不留

白話翻譯:

  • --soft:拆掉 commit,但改的東西都還在暫存區,馬上可以重新 commit
  • --mixed:拆掉 commit,改的東西退回工作目錄,需要重新 add
  • --hard核彈級操作,回退後什麼都不留。用之前三思

回退兩次?用 HEAD~2。回退到特定 commit?用 git reset --soft abc1234

revert:公共分支上的安全撤銷

git revert commit-hash

跟 reset 不同,revert 會產生一個「反向 commit」來撤銷指定的提交,不會重寫歷史。在公共分支上要撤銷東西,永遠用 revert 而不是 reset。

stash:臨時口袋

正在做一件事,還不想提交,但又要切換分支處理緊急問題?

git stash                           # 把當前進度塞進口袋
git stash save "描述訊息"            # 帶備註的 stash
git stash list                      # 看口袋裡有什麼
git stash pop                       # 拿出來並刪除 stash
git stash apply stash@{1}           # 拿出特定的 stash(不刪除)
git stash drop stash@{1}            # 丟掉特定的 stash

實際場景:你在開發新功能,老闆突然說線上有 bug 要修。

git stash save "開發到一半的新功能"
git checkout main
git checkout -b hotfix/urgent-bug
# 修 bug、提交、合併...
git checkout feature-branch
git stash pop   # 回來繼續

cherry-pick:精準搬運

git cherry-pick commit-hash

從另一個分支挑一個 commit 搬到當前分支。比如同事在 A 分支修了一個 bug,你的 B 分支也需要這個修復,直接 cherry-pick 過來就好,不用合併整個分支。

reflog:Git 的黑盒子

git reflog

即使你用 reset --hard 搞砸了什麼,reflog 通常還能救你一命。它記錄了你做過的所有 Git 操作,包括那些「已經消失」的 commit。

找到你要回去的那個點,然後 git reset --hard <hash> 就能回去了。所以嚴格來說,在 Git 裡幾乎沒有什麼是真正不可逆的。

tag:標記版本

git tag v1.0.0                                    # 輕量標籤
git tag -a v1.0.0 -m "Release version 1.0.0"     # 附註標籤
git push origin v1.0.0                             # 推送標籤

標籤通常用在版本發佈的時候,讓你能快速找到某個版本對應的程式碼。更多關於版本發佈的內容,看 Release 管理

好用的檢視指令

git log --graph --oneline --all    # 漂亮的分支圖
git diff --staged                   # 看暫存區裡改了什麼

在提交前跑一下 git diff --staged 檢查內容,是個好習慣。


學完這篇和 上篇,你的 Git 功力已經超過大部分初階工程師了。但別驕傲,Git 的坑永遠比你想像的深。問問那些 force push 到 main 的人就知道了。


延伸閱讀