Git 進階指南:實用技巧與最佳實踐
即使使用
git
多年,仍然難免會遇到某些操作模糊不清、總是記不住該怎麼做的情況。有時,即便知道目標操作,因為使用頻率不高,還是會感到猶豫,擔心一個不小心就讓已有的修改付諸東流。這篇文章整理了一些常見但容易被遺忘的
git
操作,希望能幫助大家應對這些困擾。
⚠️請注意:本文適合對
git
有一定瞭解的讀者。如果您需要學習
git
的基礎知識,建議先參閱筆者的「Git 入門指南」。
目錄
- Git 有沒有後悔藥?做錯操作後還能回到從前嗎?
- 如何刪除所有的 commit 歷史?
- 如何修改最新的 commit 內容?
- 當 upstream repo 有大幅變更時,如何將自己的 commit 加到最新的 upstream 版本之後?
- 當需要一個共享的 repo 時,該怎麼做?
Git 有沒有後悔藥?做錯操作後還能回到從前嗎?
每個人都會犯錯,尤其是使用
git
這樣強大而靈活的工具時,一個不小心就可能導致錯誤操作。幸運的是,git
內建了「後悔藥」,讓我們有機會撤銷錯誤並回溯到之前的狀態。
⚠️ 請注意:下面的
git reset --hard
會捨棄工作區的修改,因此如果你還有未提交的變更,請務必先使用
git stash
暫存它們,回退後再用
git stash pop
取回之前暫存的修改。
操作步驟:
# 顯示所有的 git 操作記錄(包括 reset、checkout、merge 等)
git reflog
# 找到出錯前的 commit(透過 reflog 顯示的 commit hash)並且 reset
git reset --hard <commit-hash>
git reflog
是一個強大的命令,其中記錄了 repo 中所有的
HEAD 變動,甚至包括已經刪除的 commit。因此,即使你誤用了
git reset --hard
或
git rebase
這類會覆蓋歷史的操作,通常仍能透過
reflog
找回遺失的 commit。
如何刪除所有的 commit 歷史?
刪除所有 commit 歷史的情境並不常見,尤其是在多人協作的開源項目中,不建議這麼做。即使是個人專案,也應該謹慎操作。如果你的目標只是對部分 commit 進行清理,那 GitLab 的這篇文章:「How (and why!) to keep your Git commit history clean」 可供參考。
⚠️ 請注意:使用這個方法清理 commit
歷史後,理論上仍然可以恢復,這是
git
設計的特性。因此,如果你的目標是刪除 commit
中意外洩漏的敏感資訊,最好的做法是刪除整個 repo,然後重新建立一個新的
repo。
操作步驟:
# 建立一個新的 orphan branch
git checkout --orphan tmp_branch
# 添加所有文件
git add -A
# 提交新的初始 commit
git commit -am "Initial commit"
# 刪除舊的 master branch
git branch -D master
# 將當前 branch 重新命名為 master
git branch -m master
# 強制推送至遠端 repo
git push -f origin master
執行完這些步驟後,repo 只會保留一個新的 commit,清理之後的感受真的太爽了!就像清空回收站一樣~但還是要再次強調,請謹慎操作!
如何修改最新的 commit 內容?
在 commit 之後,經常會發現某些細節需要修正。幸好,git
提供了一個方便的方法來更新最新的 commit,而不需要額外增加一次 commit
記錄。
操作步驟:
git add . # 添加修改內容
git commit --amend --no-edit # 更新 commit,內容不變
⚠️ 請注意:如果這個 commit 已經推送到遠端,使用
--amend
之後,你需要強制推送 (git push --force
),這可能會影響其他人的協作,因此務必謹慎!
如果你還想修改 commit message,只需省略 --no-edit
:
git commit --amend
這樣 git
會彈出編輯器,讓你修改 commit message。
當 upstream repo 有大幅變更時,如何將自己的 commit 加到最新的 upstream 版本之後?
在貢獻開源專案時,可能會遇到 upstream repo 進行了大幅變更,導致你的 fork 落後於最新的 upstream master。這種情況下,如果你的修改尚未推送到遠端,與其解決複雜的 merge 衝突,不如直接將你的 commit 重新應用到最新的 upstream 版本。
操作步驟:
⚠️
請在操作前記下自己需要保留的 commit
hash,以防萬一!如果忘記了,可以使用
git reflog
找回。
# 確保你在自己想要保留 commit 的 branch 上
git checkout your-feature-branch
# 取得 upstream 最新變更並重置當前的 branch
# 這裏的 upstream 是我們自行設置的 remote,也可以替換成任何 remote
# 這裏假設我們想要更新到 upstream 的 master branch,實際上可以是任何 branch
git fetch upstream
git reset --hard upstream/master
# 重新應用之前的 commit(使用記下的 hash)
git cherry-pick <your-modified-commit-hash>
# 將變更強制推送到你自己的遠端 repo
git push --force
這樣,你的 commit 就會被乾淨地加到 upstream 的最新 commit 之後,而不會產生不必要的 merge 衝突。
當需要一個共享的 repo 時,該怎麼做?
使用
git
的一大場景就是與他人合作寫程式,通常人們會直接選用已有的在線服務,但如果我們想自己創建一個共享
repo 應該怎麼做呢?在 git
中,bare repo
是一種沒有工作目錄的 repo,通常作為共享的 remote repo
來使用。例如,當團隊需要一個中央版本庫來同步各自的修改時,就可以建立一個
bare repo 來充當 remote repo。
操作步驟:
# 建立一個 bare repository
git init --bare my_project.git
執行後,my_project.git
目錄內部會包含
HEAD
、objects/
、refs/
等
git
相關文件,但不會有實際的工作目錄,因此無法直接編輯程式碼。
其使用方式也很簡單,只需要將其當做 remote repo,然後開發者透過
git clone
或
git push
來與其互動就可以了。例如:
# 將本地 repo 推送到 bare repository
git remote add origin /path/to/my_project.git
git push -u origin master
由於 bare repo 沒有工作區,因此不能直接在其中執行
git commit
或
git checkout
等操作,這也是為什麼它適合作為 remote
repo,而非日常開發使用的 repo。
在多人協作或自建 git
伺服器時,bare repo
是常見的架構選擇,可以讓開發團隊更方便地共享代碼並進行版本控制。
希望這些 git
技巧能幫助大家更順利地管理版本控制!其實,在
git
中往往有多種方法可以達成相同的目標,而不同的情境可能適用不同的解決方案。靈活運用各種技巧,理解其背後的原理,並舉一反三,才能真正發揮
git
的強大功能,讓版本控制變得更加高效與順手!(^u^)