iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Security

從0基礎開始起飛,一起一步步踏入資安系列 第 18

[ Day 18 ] 更多的Git指令進階教學 ( Linux指令 - git )

  • 分享至 

  • xImage
  •  

以下接續昨天,更多git的指令教學

git reset

移動分支指標 & 處理暫存/工作區

git reset 的本質是 把目前分支的 HEAD(指向某個 commit 的指標)移到另一個 commit,同時可決定要不要改變暫存區或工作目錄。

三種常用模式

模式 指令範例 會發生什麼事(簡單)
--soft git reset --soft <commit> 只移動 HEAD(把 commit 撤回),保留暫存區與工作目錄不動
--mixed(預設) git reset <commit>git reset --mixed <commit> 移動 HEAD,把暫存區還原到該 commit
--hard git reset --hard <commit> 移動 HEAD,重置暫存區與工作目錄到該 commit

常見範例

1. 把最後一次 commit 撤回,但保留變更在暫存區

(想改 commit 訊息或再加入檔案)

git reset --soft HEAD~1
  • HEAD~1 = 前一個 commit
  • 上一個 commit 的內容會回到「暫存區」,你可以 git commit --amend 或重新編輯 commit message。

2. 把最後一次 commit 撤回,保留變更在工作目錄

(但不在暫存區)

git reset HEAD~1
# 等同 git reset --mixed HEAD~1
  • 結果:檔案改動變成 git status 裡的「修改但未 staged」。

3. 完全回到某個 commit

(會丟掉本地未提交的改動)

git reset --hard a1b2c3d4
  • a1b2c3d4 是 commit hash
  • 會刪除暫存與工作目錄中尚未 commit 的變更(不可逆,但可用 reflog 有機會找回,下面會寫到)。

4. 把分支強制回到遠端 origin/main 的狀態

(把本地改動捨棄,讓本地與遠端一致)

git fetch origin
git reset --hard origin/main
  • 小心:這會丟掉你本地尚未 commit 的所有改動。

5. 取消已 git add 的檔案(unstage)

git reset HEAD file.txt
  • 只把 file.txt 從暫存區拿掉,變成修改但未 staged ( 已修改但未加入暫存區 )。

git revert

安全在公開歷史上撤銷

git revert <commit> 會在歷史上新增一個「反向 commit」,它的效果是取消指定 commit 的改動,但保持歷史完整(不改寫已存在的 commit)。

適合已經 push 到遠端、需要撤銷但不能改寫歷史的情況。

範例:

git revert a1b2c3d4
# 會互動要求輸入 revert 的 commit message,或用 -m 指定
  • 新增一個 commit,內容與 a1b2c3d4 的變動互相相反 ( 回到原本狀態 )。
  • 適合團隊協作時使用。

git reflog

救火工具:找回走掉的 HEAD

  • git reflog 記錄了你本地 HEAD 的每一次移動(例如 commit、reset、checkout 都會留下紀錄)。
  • 這是你做 git reset --hard、誤刪分支、或執行 commit --amend 後找回「關鍵 commit」的第一條路徑。reflog 是本地的(不會上傳到遠端),會在本地保留一段時間(預設多久取決於 Git 設定,通常 90 天)。

如何用 reflog 找回丟失的 commit

步驟:

  1. 查看 reflog 找回最近的 HEAD 歷史
git reflog

輸出可能像:

a1b2c3d (HEAD@{0}): reset: moving to HEAD~2
c3d4e5f (HEAD@{1}): commit: 新增功能 X
d4e5f6a (HEAD@{2}): commit: 修 bug Y
...
  1. 找到你想恢復的 commit hash(例如 c3d4e5f),然後建立新分支或把分支指回去:
git checkout -b recovery c3d4e5f
# 或把 main 指回去
git reset --hard c3d4e5f
  • 如果你不想直接 reset --hard,可以先 git checkout -b recover <hash>,確認內容沒問題再決定下一步。

git restore

(取代某些 checkout 用法,較新)

  • 取消工作目錄的改動(恢復到最後一次 commit 的版本):
git restore file.txt
  • 取消暫存(unstage):
git restore --staged file.txt

這兩個功能在舊版 Git 常用 git checkout -- file.txt 與 git reset HEAD file.txt,新寫法更直觀。

git cherry-pick

(把單一 commit 套到另一分支)

git cherry-pick a1b2c3d
  • 適用於你在 feature 分支做了一個小修,想把那個修直接帶到 main,不用合併整個分支。

git rebase -i

互動式改寫歷史

git rebase -i HEAD~3
  • 會打開編輯器,列出最近 3 次 commit,可以 picksquashreword 等操作來合併或修改 commit。
  • 不建議在已經推到遠端(公開)分支上改寫歷史,除非你和團隊協調。

git bisect

(二分法找出壞 commit)

  • 當某次提交引進 bug,用二分法快速定位是哪一個 commit:
git bisect start
git bisect bad        # 當前版本有 bug
git bisect good v1.2  # 指定一個已知沒有 bug 的 commit/tag
# Git 會自動 checkout 到中間 commit,跑測試然後 git bisect good/bad
# 最終會告訴你引起 bug 的 commit
git bisect reset

git stash

(臨時放下未完成工作)

  • 暫存修改並恢復乾淨工作目錄:
git stash push -m "WIP: new feature"
# 查看 stash
git stash list
# 恢復(套用)
git stash pop
# 從 stash 建分支
git stash branch fix-branch stash@{0}

git clean

(刪除未追蹤檔)

  • 先預演(dry-run)
git clean -nd
  • 確認後刪除未追蹤檔與目錄
git clean -fd
  • 會刪除未追蹤的檔案,無法 recover(除非你有備份或 reflog 找到之前的 commit 有它)。

上一篇
[ Day 17 ] Git進階篇(1) ( Linux指令 - git )
下一篇
[ Day 19 ] 來反轉一切吧 ! Linux指令 - rev / tac
系列文
從0基礎開始起飛,一起一步步踏入資安23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言