如何将当前分支合并到另一个分支中?

192

我有两个分支:主分支(master)和开发分支(dev)。我通常在开发分支上进行工作,只有在经过生产环境批准后,才会将代码提交到主分支。当我这样做时,我必须执行以下操作:

git checkout master
git merge dev
git checkout dev

这种方法十分冗长,而且我经常使用,想要最小化它。有没有一条git命令可以让我从当前分支 dev 合并到其他分支 master,而不必先切换到 master 分支呢?可能类似于这样的命令:

git merge dev to master

这将非常棒。我查阅了git文档,但没有找到任何相关内容。


12
推送的建议是什么意思?那是用于更新“远程”,而不是在自己的存储库中合并。 - Cascabel
4
Jefromi说得对,push在这里没有用。我是在谈论另一个本地分支,而不是远程分支。 - Chris
3
更糟糕的是当您有未提交的本地更改时:git stashgit checkout mastergit merge devgit checkout devgit stash pop - Mu Mind
2
好问题。我也想知道这个,因为我想拉取到一个非当前分支。我想避免切换分支,因为我有一个流程,如果工作树中的任何文件发生更改,就会启动构建。 - Kelvin
1
@Qix,他的意思不是这样的。你不能在同一个仓库的两个分支之间进行推送。推送是用于在不同的仓库之间移动更改,而不是在同一个仓库的不同分支之间移动。 - Chris
显示剩余7条评论
8个回答

97

1. 为您的本地仓库添加一个远程别名,例如:

git remote add self file:///path/to/your/repository

(或者在Windows上使用git remote add self C:\path\to\your\repository)

2. 推送到self远程仓库,例如:

git push self dev:master

2
子模块!这不仅解决了所提出的问题,还解决了只有一个子模块时切换分支的问题。太棒了! - eddiemoya
2
+1 这很有创意,完全不会影响工作树。只是澄清一下:/path/to/your/repository 是您的工作树路径,即不包括 .git 目录。另外,这应该是不言而喻的:如果您移动了存储库,则必须更新远程。 - Kelvin
2
@JosephK.Strauss 你可以先将主分支(master)合并到当前分支(dev),然后使用 git push self dev:master 推送合并提交。 - Leonid Shvechikov
@LeonidShvechikov 是的,但这将使父级顺序相反。 - Joseph K. Strauss
5
为什么要使用远程别名?我觉得git push . head:master很好用。 - geon
显示剩余5条评论

64

@zerome 的当前最高票答案很好,但有点不必要地啰嗦。

在您的git仓库基础目录下,您只需要执行这个命令:git push . dev:master

一个更通用的解决方案是在任何地方都适用的:

git push $(git rev-parse --show-toplevel) dev:master

3
git push . dev:master 简化了我的生活!迄今为止最好的答案,谢谢。 - Jeremy Belolo
你打算将合并后的主分支推送到像Github这样的远程代码库吗?通过执行 git push origin dev:master 可以省略一步。 - Alex R
1
能否使用这个来复制 merge --no-ff 的行为? - exhuma
2
我在Windows中遇到了“Invalid remote name“.””错误。我是否仍需要执行git remote add self file:///myRepo命令? - kiewic
1
但这并没有真正执行合并操作... 如果开发分支领先于主分支那还好,但如果不是呢? - Thomas Levesque

45

你最好的选择是使用别名,在全局gitconfig文件中定义(~/.gitconfig):

[alias]
    merge-to = "!f() { git checkout $1 && git merge $2 && git checkout -; }; f"

这样你就可以从任何存储库中调用它

git merge-to master dev

3
如果合并不是自动的,而需要手动解决合并冲突,会发生什么?(在这种情况下,我假设主分支上没有进行任何工作,因此不太可能发生,但还是想知道会发生什么) - Stein G. Strindhaug
@Stein:由于我使用的是 &&,而不是 ;,它会导致合并失败,而不会尝试切换回去。希望用户足够聪明,能看到“合并失败”的消息并处理它。 - Cascabel
@Stein:如果你知道合并应该是快进的,那么你可以完全不用检出就进行合并,但是OP似乎不是这种情况。 - Cascabel
6
我更喜欢这个 merge-to = "!f() { export tmp_branch=git branch | grep '* ' | tr -d '* '; git checkout $1 && echo git merge $tmp_branch && echo git checkout $tmp_branch; unset $tmp_branch; }; f",它让我不必输入当前所在的分支名称。因此,如果我想把 dev 合并到 master,并且我现在在 dev 分支上,我只需要输入 git merge-to master - Steve
3
更好的版本,包括正确的反引号和没有回显:merge-to = "!f() { export tmp_branch=\git branch | grep '* ' | tr -d '* '`; git checkout $1 && git merge $tmp_branch && git checkout $tmp_branch; unset $tmp_branch; }; f"`。该命令是一个Git别名,用于将当前分支合并到另一个指定的分支。变量“tmp_branch”被用来存储当前所在的分支,然后切换到目标分支,将当前分支合并进去,最后再切换回原始分支。完成后,“tmp_branch”变量将被删除。 - Simon Epskamp
3
unset 命令不正确。更正为: merge-to = "!f() { export tmp_branch=git branch | grep '* ' | tr -d '* '; git checkout $1 && git merge --no-ff $tmp_branch && git checkout $tmp_branch; unset tmp_branch; }; f" - 5422m4n

38

这是对Jefromi的小修改,不需要您输入当前分支。

因此,您可以像这样使用它:git merge-to dev

它将切换到dev分支,将其与CURRENT合并,然后再切换回来。

例如,假设您在master分支上,它将把master合并到dev中,并且您仍然在master上。

它绝对会出现在我的dotfiles中 :)

[alias]
  merge-to = "!gitmergeto() { export tmp_branch=`git branch | grep '* ' | tr -d '* '` && git checkout $1 && git merge $tmp_branch && git checkout $tmp_branch; unset tmp_branch; }; gitmergeto"

6

虽然这篇文章有些旧,但以下是将@kevin-lyda和@dmytrii-nagirniak的解决方案结合起来的一个别名。该别名可以将当前分支合并到指定的分支中。它使用remotes方法,并使用git命令获取上下文。

[alias]
    merge-to = "!gitmergeto() { git push \"`git rev-parse --show-toplevel`\" `git rev-parse --abbrev-ref HEAD`:$1; } && gitmergeto"

用法如下:

git merge-to other-branch-name

5

将当前分支合并到另一个分支而无需检出另一个分支:

快进式合并

这非常简单。根据定义,快进式合并只是意味着分支指针在提交树中向前移动。所以你需要做的就是 模拟 这个过程:

git branch -f master dev

注意: 这假定 master 指向一个在 dev 分支或其他分支中的提交。如果不是,请注意,您可能会丢失工作!git merge 不同的是,当无法进行快进合并时,它将创建合并提交(或者报错),但此方法则默默强制分支指针指向另一个提交。

这也假设您是该仓库唯一的工程师,或者您知道自己在做什么。

提示:如果您执行了 git fetch 并且 origin/master 中有新的提交,您可以使用以下命令在不检出的情况下移动 master 分支:

git branch -f master origin/master

通过合并提交进行合并

这并不总是可能的。要创建一个合并提交,您必须执行合并操作。而要执行合并操作,您应该有其他分支中不在当前分支中的提交。

如果master分支中有不在dev分支中的提交,您可以:

免责声明:这只是一个概念验证,仅仅证明有时候可以在不检出的情况下向另一个分支进行合并。如果您想每天使用它,您可能需要使用shell重定向为其创建别名或者制作一个shell脚本。当然,您也可以为问题中显示的较短过程创建一个shell脚本。

git checkout -b temp
git merge --no-ff -e master
git branch -f master temp
git checkout dev
git branch -D temp

说明:

  1. Check out a temporary branch that points to the same commit as current branch.
  2. Merge master into the temporary branch and launch commit message editor. If you want the merge commit to look like you had merged the dev branch into master, edit it from this:

    Merge branch 'master' into temp
    

    to this:

    Merge branch 'dev'
    

    Tip: You can use -m "Merge branch 'dev'" instead of -e to be quicker.

  3. Update the master branch pointer to point to the merge commit.
  4. Check out the dev branch.
  5. Force delete the temporary branch.
这仍然会涉及到您的工作树,但最小化。它不会将树回滚到原始的“master”状态,只是为了再次引入开发更改。有些人可能不关心,但对于其他人来说可能很重要。

1
很多时候,您想要合并当前分支的分支是来自于之前的一个分支。这种情况下,您可以执行以下命令:git co - && git merge @{-1},例如:
git checkout somebranch      // (while on master)

// add some commits

git co - && git merge @{-1}  // will merge somebranch into master

1

我的解决方案与其他答案类似,但有以下不同之处:

  • 函数为了可读性而分成多行
  • 函数调用set -ex,因此每个命令都会打印出来,如果命令失败,函数将立即退出
  • 别名将其参数传递给git merge,除了第一个目标分支
  • 函数包括一个空命令: git merge,确保在某些shell设置(例如oh-my-zsh的gitfast)中可以使用制表符补全
[alias]
  merge-to = "!f() { : git merge ; \
      set -ex ; \
      local this=$(git rev-parse --abbrev-ref HEAD) ; \
      local target=$1 ; \
      shift ; \
      git checkout $target ; \
      git merge $this \"$@\" ; \
      git checkout $this ; \
    } ; f"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接