場景:把本地倉庫全量推送到遠端的空倉庫,保留提交歷史,所有分支,所有tag;
大部分程式碼託管服務都會有免費推送的限制(如gitlab,
如上的失敗,可以透過git 命令,批次改寫提交歷史來解決;
本文以在GitHub建立遠端的空倉庫為例,介紹本地倉庫推送至遠端倉庫,保留提交歷史,所有分支,所有tag,和批次改寫提交歷史的步驟,以解決『大體積的歷史commit無法推送到遠端倉庫』的問題;
1 新建遠端的空倉庫
不要新增預設的README,倉庫必須為空,否則會push失敗;
2 改寫本地倉庫的遠端目標倉庫
cd <你的本地倉庫路徑>/ # 檢視遠端目標 git remote -v # 刪除遠端目標 git remote rm origin # 或者,你也可以更改原有的遠端目標的名字 # git remote rename origin old-origin git remote -v # 新增1.1節中新建的遠端倉庫 git remote add origin git@github.com:<你的GitHub使用者名稱>/<你的倉庫名>.git git remote -v
3 推送所有分支/tag到遠端
# 推送所有分支到名為origin的遠端目標 git push -u origin --all # 和 git push --set-upstream origin --all 是一樣的 # 推送所有tag到名為origin的遠端目標 # !! 推送tags仍然失敗了,推測是需要切到每一個tag,每一個tag都需要刪除大檔案的歷史;考慮到全量tags的推送並不重要,作為後續的TODO; git push -u origin --tags # (可選的)你也可以,更改當前的分支名,並單獨推送該分支到遠端目標的某一分支 # 更改當前分支名為main git branch -M main # 把當前分支推送到遠端的main分支 git push -u origin main
4 批次改寫提交歷史
在3節,git push -u origin --all
時,報錯;
日誌中提示,有提交大於了100MB的限制;
4.1 找到大體積的檔案
find . -type f -exec du -h {} + | sort -h | tail -n20
示例輸出:
uav@uav-G5-5500:/tmp/**$ find . -type f -exec du -h {} + | sort -h | tail -n20 ... 93M ./tests/data/Tunnel.pcap 205M ./tests/data/highway.pcap 256M ./.git/objects/pack/pack-c3cfcbe650b543caf1143271c04fa51e377314b5.pack 1019M ./.git/objects/pack/pack-d77ef04279c83d523f00d9b0df8674cae91ae0a2.pack
推測大體積的提交歷史大機率是包含了pcap檔案;
4.2 刪除提交歷史中的大體積檔案
# 檢視本地分支列表; git branch # 逐個切換到每個分支,在每個分支都要執行更改提交歷史的操作; # !! 沒有找到1次變更所有分支歷史的方法,TODO; git checkout master git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch *.pcap' # ... 同樣操作其他分支;
控制檯的輸出,如下:
# ... Rewrite 431b95ba4b145f70bb13fb4d5dbc11854d4d1283 (799/808) (67 seconds passed, remaining 0 predicted) rm 'tests/data/16_highway.pcap' rm 'tests/data/Tunnel.pcap' rm 'tests/data/64.pcap' rm 'tests/data/128.pcap' Rewrite e447e530142024c1048aa3b782e6645238422b76 (799/808) (67 seconds passed, remaining 0 predicted) rm 'tests/data/16_highway.pcap' rm 'tests/data/Tunnel.pcap' rm 'tests/data/64.pcap' rm 'tests/data/128.pcap' # 提示,歷史改寫成功; Ref 'refs/heads/master' was rewritten
需要注意的地方:
# 使用*.pcap進行匹配,如果使用.pcap,會匹配失敗,顯示分支未修改; git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch .pcap' WARNING: git-filter-branch has a glut of gotchas generating mangled history rewrites. Hit Ctrl-C before proceeding to abort, then use an alternative filtering tool such as 'git filter-repo' (https://github.com/newren/git-filter-repo/) instead. See the filter-branch manual page for more details; to squelch this warning, set FILTER_BRANCH_SQUELCH_WARNING=1. Proceeding with filter-branch... Rewrite e447e530142024c1048aa3b782e6645238422b76 (802/808) (67 seconds passed, remaining 0 predicted) # 提示分支未修改; WARNING: Ref 'refs/heads/master' is unchanged
4.3 再次推送
參考3節;
git push -u origin --all
5 使用LFS推送大檔案
LFS(Large File Storage)透過把大檔案儲存放在Git倉庫之外,並在Git倉庫中儲存檔案的指標,從而實現對大檔案的管理;
如果仍然有大檔案的推送需求,可以使用LFS,TODO;
x 參考
一些常用的git命令:
Git命令 | 作用 | 備註 |
---|---|---|
git config -l | 列出當前git倉庫或全域性配置的所有配置項及其值; | 倉庫級別的配置項儲存在倉庫的.git/config檔案中;全域性級別的配置項儲存在您使用者目錄下的.gitconfig檔案中; |
git pull github main | 從名為github的遠端倉庫的main分支拉取最新的修改,並將其合併到當前所在的本地分支中; | 如果存在衝突,需要手動解決衝突後再進行提交; |
x.1
x.2
x.3
x.4
x.5
x.6
x.7
x.8
x.9
x.10