我在一个有两个分支a和B的项目上工作。我通常在分支a上工作,并合并分支B中的内容。对于合并,我通常会这样做:
git merge origin/branchB
但是,我也希望保留分支B的本地副本,因为我可能会偶尔检查分支,而不必首先与分支a合并。为此,我会:
git checkout branchB
git pull
git checkout branchA
有没有一种方法可以在一个命令中完成上述操作,而不必来回切换分支?我应该使用gitupdate-ref吗?怎样
我在一个有两个分支a和B的项目上工作。我通常在分支a上工作,并合并分支B中的内容。对于合并,我通常会这样做:
git merge origin/branchB
但是,我也希望保留分支B的本地副本,因为我可能会偶尔检查分支,而不必首先与分支a合并。为此,我会:
git checkout branchB
git pull
git checkout branchA
有没有一种方法可以在一个命令中完成上述操作,而不必来回切换分支?我应该使用gitupdate-ref吗?怎样
当前回答
正如Amber所说,快进合并是唯一可以想象得到的情况。任何其他合并都可能需要经过整个三方合并,应用补丁,解决冲突-这意味着需要有文件。
我身边正好有一个脚本:在不接触工作树的情况下进行快速向前合并(除非您要合并到HEAD)。它有点长,因为它至少有点健壮——它检查以确保合并是快速前进的,然后在不检查分支的情况下执行它,但会产生与之前相同的结果——您可以看到更改的diff-stat摘要,并且reflog中的条目与快速前进的合并完全相同,而不是使用branch-f时得到的“重置”结果。如果将其命名为gitmergeff并将其放到bin目录中,则可以将其作为git命令调用:gitmergeff。
#!/bin/bash
_usage() {
echo "Usage: git merge-ff <branch> <committish-to-merge>" 1>&2
exit 1
}
_merge_ff() {
branch="$1"
commit="$2"
branch_orig_hash="$(git show-ref -s --verify refs/heads/$branch 2> /dev/null)"
if [ $? -ne 0 ]; then
echo "Error: unknown branch $branch" 1>&2
_usage
fi
commit_orig_hash="$(git rev-parse --verify $commit 2> /dev/null)"
if [ $? -ne 0 ]; then
echo "Error: unknown revision $commit" 1>&2
_usage
fi
if [ "$(git symbolic-ref HEAD)" = "refs/heads/$branch" ]; then
git merge $quiet --ff-only "$commit"
else
if [ "$(git merge-base $branch_orig_hash $commit_orig_hash)" != "$branch_orig_hash" ]; then
echo "Error: merging $commit into $branch would not be a fast-forward" 1>&2
exit 1
fi
echo "Updating ${branch_orig_hash:0:7}..${commit_orig_hash:0:7}"
if git update-ref -m "merge $commit: Fast forward" "refs/heads/$branch" "$commit_orig_hash" "$branch_orig_hash"; then
if [ -z $quiet ]; then
echo "Fast forward"
git diff --stat "$branch@{1}" "$branch"
fi
else
echo "Error: fast forward using update-ref failed" 1>&2
fi
fi
}
while getopts "q" opt; do
case $opt in
q ) quiet="-q";;
* ) ;;
esac
done
shift $((OPTIND-1))
case $# in
2 ) _merge_ff "$1" "$2";;
* ) _usage
esac
注:如果有人看到该脚本有任何问题,请评论!这是一份写就忘的工作,但我很乐意改进它。
其他回答
我为每天在项目中遇到的类似用例编写了一个shell函数。这基本上是一个快捷方式,可以让本地分支机构在打开PR之前保持与公共分支机构的最新状态,如开发等。
即使你不想使用结账,也要发布这个,以防其他人不介意这种限制。
glmh(“git pull and merge here”)将自动签出分支B,拉取最新的分支,重新签出分支A,并合并分支B。
不需要保留branchA的本地副本,但可以通过在签出branchB之前添加一个步骤来轻松修改。类似于。。。
git branch ${branchA}-no-branchB ${branchA}
对于简单的快进合并,这将跳到提交消息提示符。
对于非快速合并,这将使分支处于冲突解决状态(您可能需要进行干预)。
要进行设置,请添加到.bashrc或.zshrc等:
glmh() {
branchB=$1
[ $# -eq 0 ] && { branchB="develop" }
branchA="$(git branch | grep '*' | sed 's/* //g')"
git checkout ${branchB} && git pull
git checkout ${branchA} && git merge ${branchB}
}
用法:
# No argument given, will assume "develop"
> glmh
# Pass an argument to pull and merge a specific branch
> glmh your-other-branch
注意:这不足以将分支名称以外的参数传递给gitmerge
不需要git签出,就可以进行任何合并,甚至是非快速合并。@grego的工作树回答是一个很好的提示。要对此进行扩展,请执行以下操作:
cd local_repo
git worktree add _master_wt master
cd _master_wt
git pull origin master:master
git merge --no-ff -m "merging workbranch" my_work_branch
cd ..
git worktree remove _master_wt
现在,您已经将本地工作分支合并到本地主分支,而无需切换签出。
您可以克隆回购并在新回购中进行合并。在同一个文件系统上,这将硬链接而不是复制大部分数据。最后将结果拉入原始回购。
您可以简单地git将原始分支B拉到分支A中,git将为您完成此操作。
git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]
你可以尝试git worktree让两个分支并排打开,这听起来可能是你想要的,但与我在这里看到的其他一些答案非常不同。
通过这种方式,您可以在同一个git repo中有两个单独的分支进行跟踪,因此您只需获取一次即可在两个工作树中获取更新(而不必分别获取两次git clone和git pull)
Worktree将为您的代码创建一个新的工作目录,您可以在其中同时签出不同的分支,而不是在原地交换分支。
当您想要删除它时,可以使用
git worktree remove [-f] <worktree>