Git 各種日常問題集合 - 遠端
Git 教學現在有獨立的網站了!請移駕 Git 零到一百。
都是簡單的日常問題但是要花一點時間搜尋,所以這篇文章集中列出方便查詢。
一次清除遠端所有分支
發了一堆 PR 被合併後該如何快速清除?
git remote prune origin
一次清除所有被合併的分支
請使用此腳本而不是浪費時間在背指令、找小抄:
腳本
#!/usr/bin/env bash
# delete_merged_branch - 刪除已合併的 Git 分支
#
# Usage:
# delete-merged-branch # 只刪除本地已合併分支
# delete-merged-branch true # 刪除本地與遠端(使用 origin)
# delete-merged-branch true NAME # 刪除本地與遠端 upstream NAME
set -e
DELETE_REMOTE="${1:-false}"
REMOTE_NAME="${2:-origin}"
COLOR_YELLOW='\033[33m'
COLOR_RESET='\033[0m'
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Error: Not in a Git repository"
exit 1
fi
BRANCHES=$(git branch --merged | grep -v -E "^[[:space:]]*\\*|[[:space:]]*(master|main)[[:space:]]*$" | sed 's/^[[:space:]]*//')
if [ -z "$BRANCHES" ]; then
echo "No merged branches found."
exit 0
fi
echo "Found merged branches:"
echo "$BRANCHES" | while IFS= read -r branch; do
[ -n "$branch" ] && printf " ${COLOR_YELLOW}%s${COLOR_RESET}\n" "$branch"
done
echo
BRANCH_ARRAY=()
while IFS= read -r branch; do
[ -n "$branch" ] && BRANCH_ARRAY+=("$branch")
done <<<"$BRANCHES"
for branch in "${BRANCH_ARRAY[@]}"; do
if [ "$DELETE_REMOTE" = "true" ]; then
printf "Delete merged branch '${COLOR_YELLOW}%s${COLOR_RESET}' locally and from remote '${COLOR_YELLOW}%s${COLOR_RESET}'? [y/N] " "$branch" "$REMOTE_NAME"
else
printf "Delete merged branch '${COLOR_YELLOW}%s${COLOR_RESET}' locally? [y/N] " "$branch"
fi
read -r ans
case "$ans" in
[Yy] | [Yy][Ee][Ss])
# 本地分支刪除成功才會刪遠端
if git branch -d "$branch"; then
if [ "$DELETE_REMOTE" = "true" ]; then
if git push "$REMOTE_NAME" --delete "$branch" 2>/dev/null; then
printf "Deleting remote branch '${COLOR_YELLOW}%s${COLOR_RESET}' from '${COLOR_YELLOW}%s${COLOR_RESET}' successfully." "$branch" "$REMOTE_NAME"
else
printf "Fail to delete remote branch '${COLOR_YELLOW}%s${COLOR_RESET}' from '${COLOR_YELLOW}%s${COLOR_RESET}'." "$branch" "$REMOTE_NAME"
fi
fi
else
printf "Failed to delete local branch '${COLOR_YELLOW}%s${COLOR_RESET}'\n" "$branch"
fi
;;
*)
printf "Skip branch: ${COLOR_YELLOW}%s${COLOR_RESET}\n" "$branch"
;;
esac
done
printf "\nBranch cleanup completed.\n"
我的用法是儲存腳本後使用 gitconfig
把腳本加入 Git alias,例如 dm = "!delete_merged_branch"
。
遠端追蹤分支是什麼?和遠端分支一樣嗎?追蹤分支又是什麼?
遠端追蹤分支 (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 就寫的很詳細,我覺得雖然詳細但不夠清楚,而且指令有部分更新,所以統整後寫成文章。