Git将master合并到功能分支中

the*_*ega 892 git feature-branch git-flow git-branch

让我们说我们在git中有以下情况:

  1. 创建的存储库:

    mkdir GitTest2
    cd GitTest2
    git init
    
    Run Code Online (Sandbox Code Playgroud)
  2. 主服务器中的一些修改发生并得到提交.

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
    Run Code Online (Sandbox Code Playgroud)
  3. Feature1分支主,一些工作完成:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
    Run Code Online (Sandbox Code Playgroud)
  4. 同时,在主代码中发现错误并建立了修补程序分支

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
    Run Code Online (Sandbox Code Playgroud)
  5. 该错误在修补程序分支中修复并合并回主服务器(可能在拉取请求/代码审查之后):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
    Run Code Online (Sandbox Code Playgroud)
  6. feature1的开发继续:

    git checkout feature1
    
    Run Code Online (Sandbox Code Playgroud)

现在我的问题:说我需要我的功能分支中的修补程序,可能是因为那里也出现了错误.如何在不将提交复制到我的功能分支的情况下实现此目的?我想阻止在我的功能分支上获得两个与功能实现无关的新提交.如果我使用Pull请求,这对我来说尤其重要:所有这些提交也将包含在Pull Request中,并且必须进行审核,尽管已经完成(因为修补程序已经在主服务器中).

我做不到git merge master --ff-only:"致命:不可能快进,堕胎."但我不确定这是否对我有所帮助.

Sve*_*ven 1062

如何将主分支合并到功能分支?简单:

git checkout feature1
git merge master
Run Code Online (Sandbox Code Playgroud)

在这里强制进行快速合并是没有意义的,因为它无法完成.您已将两者都提交到功能分支和主分支.快进现在是不可能的.

看看gitflow.它是git的分支模型,可以遵循,你无意识地已经做到了.它也是git的扩展,它为新的工作流程步骤添加了一些命令,这些命令会自动执行,否则您需要手动执行这些操作.

那么你在工作流程中做了什么?你有两个分支可以使用,你的feature1分支基本上是gitflow模型中的"develop"分支.

您从master创建了一个修补程序分支并将其合并.现在你被卡住了.

gitflow模型要求您将修补程序也合并到devel分支,在您的情况下为"feature1".

所以真正的答案是:

git checkout feature1
git merge --no-ff hotfix1
Run Code Online (Sandbox Code Playgroud)

这会将修补程序内部所做的所有更改添加到功能分支,但仅包括这些更改.它们可能与分支中的其他开发更改冲突,但如果最终将功能分支合并回master,它们将不会与主分支冲突.

变基础时要非常小心.只有在您所做的更改保留在存储库本地时才进行rebase,例如,您没有将任何分支推送到其他存储库.重新定位是一个很好的工具,可以让你将本地提交安排到一个有用的顺序,然后再将其推向世界,但之后的重新定位会让像你这样的git初学者陷入困境.

  • 我认为值得注意的是,`git merge master`将从你的*本地*master副本中合并,所以即使你在其他人将一个不同的分支合并到master中之后你的功能分支中执行了`git pull`, '我需要'git checkout master`,然后`git pull`,然后`git checkout feature1`再来一次然后`git merge master`. (97认同)
  • @damick或者只是`git fetch`和`git merge origin/master` (46认同)
  • 这应该是公认的答案.它也适用于GitHub的拉取请求功能. (39认同)
  • @damick @ yngvar-kristiansen`git pull origin master`将自动将`orgin/master`合并到当前分支 (14认同)
  • 否.修复错误的提交仅在修补程序分支中出现一次,即使分支名称在合并到主分支和devel分支后被删除.合并提交仅显示合并引入的更改,看起来像重复提交.但这就是git的工作方式:分支和合并.真正的开发工作仅在非合并提交中进行,如果结果是工作软件,则仅接受合并. (5认同)
  • 这个工作流程是否会导致许多不必要的重复提交?hotfix-branch的提交被复制到我的功能分支中,然后合并回主服务器.这是否导致提交在提交日志中出现两次这一事实? (2认同)

Dav*_*ulc 548

你应该能够在master上重新分支你的分支:

git checkout feature1
git rebase master
Run Code Online (Sandbox Code Playgroud)

管理出现的所有冲突.当你使用错误修正(已经在master中)进行提交时,git会说没有任何更改,也许它们已经应用了.然后继续使用rebase(同时跳过已在master中的提交)

git rebase --skip
Run Code Online (Sandbox Code Playgroud)

如果git log在功能分支上执行a ,您将看到错误修正提交仅出现一次,并且在主要部分中.

有关更详细的讨论,请查看git rebase(https://git-scm.com/docs/git-rebase)上的Git书籍文档,其中涵盖了这个确切的用例.

================编辑其他上下文====================

这个答案专门针对@theomega提出的问题提出,考虑到他的特殊情况.注意这部分:

我想阻止我的功能分支上的提交与功能实现无关.

将他的私人分支重新绑定在主人身上正是产生这种结果的原因.相比之下,将master合并到他的分支中将准确地完成他特别不希望发生的事情:添加一个与他正在通过他的分支工作的功能实现无关的提交.

为了解决阅读问题标题的用户,跳过问题的实际内容和上下文,然后盲目地阅读最佳答案,假设它将始终适用于他们(不同的)用例,请允许我详细说明:

  • 只改变私人分支机构(即只存在于您的本地仓库中并且未与其他分支机构共享).重新分享共享分支将"破坏"其他人可能拥有的副本.
  • 如果你想将分支(无论是主分支还是其他分支)的变化集成到一个公共分支中(例如,你已经推动分支打开一个拉取请求,但现在与master有冲突,你需要更新你的分支来解决这些冲突)你需要将它们合并(例如git merge master在@Sven的答案中).
  • 如果这是您的偏好,您也可以将分支合并到您的本地私有分支,但请注意,它将导致您的分支中的"外部"提交.

最后,如果您对这个答案不是最适合您的情况这一事实感到不满意,即使它是@theomega,在下面添加评论也不会特别有用:我无法控制选择哪个答案,只有@theomega.

  • 不,这不安全:如果你改变,你就会改变分支的历史,这将影响拉动分支的开发人员.inf act,git默认情况下不允许你推送一个重新分支的分支:你需要在推送覆盖带有重定义版本的分支时强制更新`-f`.小心! (130认同)
  • 好吧,我冒昧的"神圣"规则是你不要在已共享的代码上进行rebase(或以其他方式更改提交历史记录):它仅适用于本地代码.基本上,您应该在共享之前将更改重新设置为"清理".在您的情况下,您可以推送一个新的重新分支(具有不同的名称),并要求同事将他们的更改建立在该分支的基础之外(例如,通过将其本地分支重新绑定到新分支上,如上所述).然后,从Github删除`feature1`. (28认同)
  • 我参与过的大多数专业团队几乎从不使用rebase - 它们只是默认合并所有内容,因此不会发生任何历史修改.这是我的首选工作方式.另一方面,一些团队在推送之前使用rebase"清理"提交(但从未推送过后). (17认同)
  • 使用git的专业团队如何处理这个问题?请注意,仔细思考,然后做一个`-f`?或者我的完整工作流程有缺陷,因为我需要`-f`? (16认同)
  • 是的,你永远不应该改变公共分支机构.然而,OP的问题似乎涉及将对`master`的新提交集成到一个私有分支中(他提到"他的"本地分支).在这种情况下,`rebase`很好,与你提到的"清理"是一样的用例. (10认同)
  • 如果你可以扩展为什么你认为这是一个可怕的想法会很好:git docs特别给出这些作为例子的用途`rebase`https://git-scm.com/docs/git-rebase很明显你不应该'重新绑定一个公共/共享分支,但用它来重写/清理你的私有分支上的历史记录(包括将它更新为分支`master`)很好:这正是私有分支存在的原因.说'rebase`命令适用于犯错误或不理解DVCS的人似乎对我有点误导. (8认同)
  • 好的,我们假设我已经将分支推送到github以获取拉取请求(在主存储库的一个分支中).是否仍然保存git rebase(也许假设没有人检查我的分支)? (6认同)
  • 为什么这是一个可接受的答案,这不是一个可接受的解决方案. (4认同)
  • 这是一个糟糕的主意.`rebase`是处理这个问题的错误方法,处理事情几乎总是错误的.它适用于犯错误的人,或者不了解DVCS工作原理的人. (2认同)
  • @Omnifarious如果我创建了一个分支,然后在master上做了一些提交,rebase是一个可接受的选项,因为没有在新分支上进行开发? (2认同)
  • 这是非常不安全的,因为我在盲目输入后发现它.我很高兴看到这个答案不被接受. (2认同)
  • @ntj 如果您的分支与 master 没有冲突,那么您最终会得到与将 master 合并到您的分支中相同的代码库。更有可能的是,在“盲目输入”之后,您错误地解决了合并冲突(即引入的错误)​​。不幸的是,当将 master 合并到您的分支时,这(不正确的合并)会在您的代码中导致相同的问题。 (2认同)

xgq*_*rms 71

git merge

您可以按照以下步骤操作

1.合并origin/master分支到feature分支

# step1: change branch to master, and pull to update all commits
$ git checkout master
$ git pull

# step2: change branch to target, and pull to update commits
$ git checkout feature
$ git pull

# step3: merge master to feature(?? current is feature branch)
$ git merge master

Run Code Online (Sandbox Code Playgroud)

2. 合并feature分支到origin/master分支

origin/master是远程主分支,master而是本地主分支

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master

Run Code Online (Sandbox Code Playgroud)

  • 感觉 rebase 被炒作了!好旧的合并:)! (2认同)

zim*_*imi 63

基于这篇文章你应该:

  • 创建基于新版本master的新分支
  • 将旧功能分支合并到新功能分支中
  • 解决新功能分支上的冲突

这样,您的历史记录保持清晰,因为您不需要反向合并.而且你不需要如此超级谨慎,因为你不需要git rebase

  • 如果你让相关的git命令跟随每一点,那将是很好的.否则在我看来,这确实是更安全和清洁的选择. (6认同)

jkd*_*dev 25

Zimi的回答通常描述了这个过程.以下是具体内容:

1)创建并切换到新分支.确保新分支基于,master因此它将包含最新的修补程序.

git checkout master
git branch feature1_new
git checkout feature1_new

# Or, combined into one command:
git checkout -b feature1_new master
Run Code Online (Sandbox Code Playgroud)

2)切换到新分支后,合并现有功能分支中的更改.这将添加您的提交而不复制修补程序提交.

git merge feature1
Run Code Online (Sandbox Code Playgroud)

3)在新分支上,解决功能与主分支之间的任何冲突.

完成!现在使用新分支继续开发您的功能.

  • 你是对的,不应该一直这样做.仅当(1)您的功能需要更改master时,或者(2)您将要将您的分支与master合并,并且可能存在冲突.为避免混乱,您可以在合并后删除分支. (4认同)
  • 这样做的问题是,当开发人员需要针对 master 进行更新时,他们会浪费时间不断地产生新的分支。我们会制作很多很多的分支,在活跃的工作期间可能每天 3 次。您应该编写有关清理所有本地垃圾分支的说明,以及如何在远程清除它们。我们还需要有关命名所有这些分支的建议,以免混淆。没有那一点,这将使分支系统变得混乱。 (2认同)
  • 如果您已经在功能分支上提交了拉取请求并且 PR 正在进行中,则此方法效果不佳,需要在新功能分支上再次进行代码审查,并进行不必要的工作。 (2认同)

kal*_*ger 12

我添加了我的答案,与其他答案类似,但也许这将是阅读和实施最快的答案。

注意:在这种情况下不需要 Rebase。

假设我有一个repo1和两个分支masterdev-user

dev-user是在 的某个状态下完成的分支master

现在假定这两个dev-usermaster进步。

在某些时候,我想dev-user获得所有在master.

我该怎么做?

我首先进入我的存储库根文件夹

cd name_of_the_repository

然后

git checkout master 
git pull 
git checkout dev-user
git pull
git merge master 
git push 
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助处于相同情况的其他人。


小智 11

这是一个脚本,可用于将主分支合并到当前分支中.

该脚本执行以下操作:

  • 切换到主分支
  • 拉主分支
  • 切换回当前分支
  • 将主分支合并到当前分支中

将此代码保存为批处理文件(.bat)并将脚本放在存储库中的任何位置.然后单击它以运行它并设置.

:: This batch file pulls current master and merges into current branch

@echo off

:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%

FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)

echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling origin master
git pull origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE
Run Code Online (Sandbox Code Playgroud)


Bob*_*ore 10

您可以做一个"挑选"来将您需要的确切提交提取到您的功能分支.

做一个git checkout hotfix1进入hotfix1分支.然后执行a git log以获取相关提交的SHA1哈希(随机字母的大序列和唯一标识提交的数字).复制那个(或前10个左右的字符).

然后,git checkout feature1返回到您的功能分支.

然后, git cherry-pick <the SHA-1 hash that you just copied>

这会将该提交(提交)提取到您的功能分支中.这个改变将在分支中 - 你只是"挑选"它.然后,恢复工作,编辑,提交,推送等你的内心.

当最终你从一个分支执行另一个合并到你的功能分支(反之亦然)时,git会认识到你已经合并了那个特定的提交,知道它不必再次进行,只是"跳过"它.


fab*_*tto 5

补充现有的答案,因为这些命令是重复出现的,所以我们可以连续执行。鉴于我们处于功能分支中:

git checkout master && git pull && git checkout - && git merge -
Run Code Online (Sandbox Code Playgroud)

或者将它们添加到别名中:

alias merge_with_master="git checkout master && git pull && git checkout - && git merge -"
Run Code Online (Sandbox Code Playgroud)