Files
.dotfile/git/git-merge2.sh
T
laily 097fce7827 fix: make git merge2 work across worktrees
Checkout of the target branch fails when it is already used by another
worktree. Detect that worktree and merge there instead.
2026-09-10 23:04:13 +08:00

73 lines
1.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 把当前分支 merge 进目标分支;目标已在其它 worktree 时直接在那边 merge
set -euo pipefail
usage() {
cat <<'EOF'
用法: git merge2 <branch> [git merge 参数...]
把当前分支合进 <branch>,然后留在当前分支。
若 <branch> 已在其它 worktree 里 checkout,则在那个 worktree 里 merge,
不会在当前目录 checkout(避免 "already used by worktree")。
EOF
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
if [[ $# -lt 1 ]]; then
usage >&2
exit 1
fi
current="$(git symbolic-ref --short HEAD)"
target="$1"
shift
if [[ "$current" == "$target" ]]; then
echo "已经在 $target 上" >&2
exit 1
fi
# porcelain 含主 worktree;%(worktreepath) 只填 linked worktree,不能用
worktree_for_branch() {
local branch="$1"
local wt=""
local line
while IFS= read -r line || [[ -n "$line" ]]; do
case "$line" in
worktree\ *)
wt="${line#worktree }"
;;
"branch refs/heads/${branch}")
printf '%s\n' "$wt"
return 0
;;
"")
wt=""
;;
esac
done < <(git worktree list --porcelain)
return 1
}
# alias / 子进程会继承当前 worktree 的 GIT_DIR,必须清掉才能 git -C 到另一个 worktree
merge_in_worktree() {
local wt="$1"
shift
env -u GIT_DIR -u GIT_WORK_TREE git -C "$wt" merge "$@"
}
wt="$(worktree_for_branch "$target" || true)"
if [[ -n "$wt" ]]; then
echo "在 worktree 中 merge $current -> $target: $wt"
merge_in_worktree "$wt" "$current" "$@"
else
git checkout "$target"
git merge "$current" "$@"
git checkout "$current"
fi