我在一个有两个分支a和B的项目上工作。我通常在分支a上工作,并合并分支B中的内容。对于合并,我通常会这样做:

git merge origin/branchB

但是,我也希望保留分支B的本地副本,因为我可能会偶尔检查分支,而不必首先与分支a合并。为此,我会:

git checkout branchB
git pull
git checkout branchA

有没有一种方法可以在一个命令中完成上述操作,而不必来回切换分支?我应该使用gitupdate-ref吗?怎样


当前回答

如果您想保持与要合并的分支相同的树(即,不是真正的“合并”),可以这样做。

# Check if you can fast-forward
if git merge-base --is-ancestor a b; then
    git update-ref refs/heads/a refs/heads/b
    exit
fi

# Else, create a "merge" commit
commit="$(git commit-tree -p a -p b -m "merge b into a" "$(git show -s --pretty=format:%T b)")"
# And update the branch to point to that commit
git update-ref refs/heads/a "$commit"

其他回答

只有当合并是快进时,才能执行此操作。如果不是,那么git需要签出文件,以便合并它们!

仅为快进操作:

git fetch <branch that would be pulled for branchB>
git update-ref -m "merge <commit>: Fast forward" refs/heads/<branch> <commit>

其中<commit>是提取的commit,即您要快进的commit。这基本上就像使用gitbranch-f移动分支一样,只是它还将其记录在reflog中,就像您实际执行了合并一样。

拜托,拜托,请不要为不快速前进的事情而这样做,否则您只会将分支重置为另一个提交。(要检查,请查看gitmerge-base<branch><commit>是否给出了分支的SHA1。)

您可以简单地git将原始分支B拉到分支A中,git将为您完成此操作。

另一种有效的方法是:

git fetch
git branch -d branchB
git branch -t branchB origin/branchB

因为它是小写-d,所以只有在数据仍然存在的情况下才会删除它。这与@kkoehne的答案相似,只是它不强制。由于-t,它将再次设置遥控器。

我有一个与OP稍有不同的需求,那就是在合并一个拉取请求之后,创建一个新的特性分支,脱离开发(或主)。这可以在一个命令行中完成,无需强制,但它不会更新本地开发分支。这只是检查一个新的分支机构并使其基于起源/发展的问题:

git checkout -b new-feature origin/develop

不需要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

现在,您已经将本地工作分支合并到本地主分支,而无需切换签出。

我为每天在项目中遇到的类似用例编写了一个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