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.
This commit is contained in:
+2
-1
@@ -73,7 +73,8 @@
|
|||||||
pt = push origin --tags
|
pt = push origin --tags
|
||||||
ph = push origin HEAD
|
ph = push origin HEAD
|
||||||
pht = push origin --tags
|
pht = push origin --tags
|
||||||
merge2 = !sh -c '_CURRENT_BRANCH=$(git symbolic-ref --short HEAD) && git checkout $1 && git merge $_CURRENT_BRANCH && git checkout $_CURRENT_BRANCH' -
|
# 把当前分支合进目标分支后回到当前分支;目标已被其它 worktree 占用时在那边 merge
|
||||||
|
merge2 = !$HOME/.dotfile/git/git-merge2.sh
|
||||||
bg = "!f() { git branch | grep $1; }; f"
|
bg = "!f() { git branch | grep $1; }; f"
|
||||||
delbr = "!f(){ git branch -D $(git branch | grep \"\b$1\"); };f"
|
delbr = "!f(){ git branch -D $(git branch | grep \"\b$1\"); };f"
|
||||||
can = commit --amend --no-edit
|
can = commit --amend --no-edit
|
||||||
|
|||||||
Executable
+72
@@ -0,0 +1,72 @@
|
|||||||
|
#!/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
|
||||||
Reference in New Issue
Block a user