Skip to main content

Git 各種日常問題集合

都是簡單的日常問題但是要花一點時間搜尋,所以這篇文章集中列出方便查詢,分為本地問題遠端問題兩個章節。


本地問題

正確 rebase

正確使用方式是移動到子分支後再使用 git rebase main,或者直接使用 git rebase main <sub-branch> 才對,原因請見使用變基 Rebase 合併分支

為你自己學 GitGit 版本控制教學 - 用範例學 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「我正在重新命名這個檔案」。

有三種情況會用到

  1. 操作複雜時,避免 Git 視為兩個不同的檔案,例如大規模變更檔案名稱
  2. 在不區分大小寫的檔案系統上更改檔案名稱的大小寫
  3. 移動 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 可以直接封鎖錯誤來源眼不見為淨。寫圖文並茂的教學還提供所有人免費閱讀我覺得很好,但是真的錯太多了,甚至有些錯誤只要看過文檔就不會犯,也就是說連文檔都沒看過就開始寫教學文章、上網賣課,結果所有讀者都被帶歪,我在做功課時就發現所有錯誤都是前面的人錯後面就跟著全錯。