Git 各種日常問題集合
都是簡單的日常問題但是要花一點時間搜尋,所以這篇文章集中列出方便查詢,分為本地問題和遠端問題兩個章節。
本地問題
正確 rebase
正確使用方式是移動到子分支後再使用 git rebase main
,或者直接使用 git rebase main <sub-branch>
才對,原因請見使用變基 Rebase 合併分支。
為你自己學 Git 和 Git 版本控制教學 - 用範例學 rebase 都寫錯了,這最誇張,但凡看過一次文檔都不可能寫成 git rebase <子分支>
,能錯的這麼離譜=看不懂文檔=沒看。
rebase onto 指定新基底
此用法相對來說比較複雜,但是複雜的原因來自於網路上的錯誤教學,請見搞懂 Rebase Onto。
沒有信口雌黃,撰文時唯一能找到的正確文章是在搜尋結果第五頁 Git合并那些事——神奇的Rebase,如果不是因為要寫「正確的」教學筆者才沒耐心每篇都點進去看,還要在一堆錯誤裡面判斷對錯。
謎之音:正確還有必要強調喔,不是阿,網路上就一大堆「錯誤的」教學。
blob, tree, tag, commit, refs 是什麼?
refs 只是幫助人類記憶的名稱,只紀錄提交 hash 讓你直接用 refs 等於指定該提交。
其他四個是 Git 的基本構成,請見關鍵字、符號和基本組成。
HEAD 是什麼
賣課網又錯了,HEAD 代表目前檢出 (checkout) 的位置,不只是分支,真的要解釋的話他屬於文檔定義中的 commit-ish,commit-ish 代表所有能最終指向一個 commit 物件的標識符,例如 HEAD, tag, branchname, refs...。
為何要用 git mv
git mv
和一般的 mv
差異是可以讓 Git 直接索引檔案,需要這個指令的原因是 Git 會推測你要作什麼,但是操作複雜時他就猜不出來你正在重新命名,git mv
就是告訴 Git「我正在重新命名這個檔案」。
有三種情況會用到
- 操作複雜時,避免 Git 視為兩個不同的檔案,例如大規模變更檔案名稱
- 在不區分大小寫的檔案系統上更改檔案名稱的大小寫
- 移動 submodule 時
賣課網寫了這麼長一篇文章整篇都在說用途是讓我們少打一個指令,別搞笑了大哥。
移除已經提交的檔案但不刪除
git rm --cached
清除 reflog 紀錄
git reflog expire --expire=now --all
清理 .git 垃圾(無用的 commit 紀錄)
修改或是移除 commit 時,原有 commit 不會直接被刪除而是會暫存,這就是為何可以使用 reflog 還原的原因。對於這些紀錄 git 有自動清理機制,但是也可以手動清除:
git gc --aggressive --prune=now
遠端問題
遠端追蹤分支是什麼?和遠端分支一樣嗎?追蹤分支又是什麼?
遠端追蹤分支 (Remote-tracking Branch) 是本地儲存庫用來記錄遠端分支最新狀態的本地參考,其名稱格式為 <遠端名稱>/<分支名稱>
,例如預設的 origin/main
。
執行 git clone
後,Git 會自動檢出 (checkout) 一個預設的本地分支,並將其設定為追蹤分支(Tracking Branch),該分支會與對應的遠端追蹤分支建立追蹤關係。例如 git clone
後預設檢出的 main
分支,會追蹤 origin/main
這個遠端追蹤分支,而 origin/main
也可稱為 main
分支的上游分支(Upstream Branch)。
所謂口語上的遠端分支就是在遠端中的本地分支,和遠端追蹤分支是不同的概念。
無法推送
有兩種可能,遠端分支設定錯誤或者遠端提交歷史比本地還要新。
比本地還新的話就使用 git pull --rebase
,如果設定跑掉就用設定遠端分支,如果想要覆蓋就使用安全的強制推送。
還是無法推送,重設遠端分支
請見 Git 遠端指令的 找不到遠端的處理方式 段落。
安全的強制推送
你以為我要講 force-with-lease 嗎,我要說的是更少人知道的 force-if-includes,請見使用 Force if Includes 安全的強制推送,裡面還有解釋 lease 到底在「租」什麼東西。
清除隱私資料
使用任意方式把目標提交從提交歷史中移除就可以了,不用擔心 reflog 紀錄,因為 reflog 紀錄壓根就不會被推送到遠端,如果要徹底清除本地紀錄可以使用 filter-repo,內建的 filter-branch 已經不被建議使用。
賣課網又寫錯了,想想每個人的 reflog 紀錄都不一樣,那怎麼可能被推送?作者書都寫完了結果還是不知道 Git 是「分散式」的「鏡像系統」,有搞清楚分散鏡像系統就不可能說出 reflog 紀錄被推送這句話。
你可能會覺得我很嚴格,可能作者就是剛好沒想到啊,你說的沒錯,那退一步來說,要寫書教別人之前至少要測試正確性吧,看起來是沒有。
只推送部分提交
git push <遠端名稱> <指定提交>:<遠端分支名稱>
又是賣課網,10 秒能講完的事情他拍了七分鐘的影片。
加速 Clone
請見我的文章使用 Git Sparse Checkout 只下載部分專案以加速 Clone 速度。
其實 The Will Will Web 就寫的很詳細,我覺得雖然詳細但不夠清楚,而且指令有部分更新,所以統整後寫成文章。
End
網路文章真的錯的太荒謬,還好有 uBlacklist 可以直接封鎖錯誤來源眼不見為淨。寫圖文並茂的教學還提供所有人免費閱讀我覺得很好,但是真的錯太多了,甚至有些錯誤只要看過文檔就不會犯,也就是說連文檔都沒看過就開始寫教學文章、上網賣課,結果所有讀者都被帶歪,我在做功課時就發現所有錯誤都是前面的人錯後面就跟著全錯。