Git将主合并到功能分支


1012

假设我们在Git中有以下情况:

  1. 创建的存储库:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. 在主服务器中进行一些修改并提交:

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1从master分支出来,并完成了一些工作:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. 同时,在主代码中发现一个错误,并建立了一个修补程序分支:

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. 该错误已在hotfix分支中修复,并重新合并到master中(可能在请求请求/代码审查之后):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. 继续对feature1进行开发:

    git checkout feature1
    

假设我在功能分支中需要此修补程序,也许是因为该错误也发生在这里。如何在不将提交复制到功能分支的情况下实现此目标?

我想防止在功能分支上获得两个与功能实现无关的新提交。如果我使用拉取请求,这对我来说尤其重要:所有这些提交也将包含在拉取请求中,尽管已经完成(因为此修补程序已在主服务器中),但必须进行审查。

我不能做一个git merge master --ff-only:“致命的:不可能快速前进,中止。”但是我不确定这是否对我有帮助。


8
如果分支feature1完全位于本地,请查看git rebase
Jokester

19
谢谢,作为git的初学者,git rebase对我来说似乎就像是黑魔法……
theomega 2013年

13
如果该分支是功能部件 -则不应在此处进行错误修复(至少在不是阻塞性错误的情况下),因为该分支的目的是展示新功能。与存在修订的提交的母版合并后,该错误将被修复。
gipi 2013年

21
对于初学者来说,可能值得一提的是git branch feature1git checkout feature1可以将3. 和可以合并为git checkout -b feature14.的内容完全减少为git checkout -b hotfix1 master
Naruto Sempai 2015年

3
您是否愿意回来并更改接受的答案,因为当前接受的答案很糟糕。
全方位

Answers:


1212

我们如何将master分支合并到feature分支?简单:

git checkout feature1
git merge master

在此处强制快速向前合并没有意义,因为它无法完成。您已同时提交到功能分支和主分支。现在快进是不可能的。

看看GitFlow。它是git的分支模型,可以遵循,而您不知不觉已经做到了。它也是Git的扩展,它为新的工作流程步骤添加了一些命令,这些命令会自动执行您原本需要手动执行的操作。

那么您在工作流程中做了什么呢?您有两个分支可以使用,feature1分支基本上是GitFlow模型中的“ develop”分支。

您从master创建了一个修补程序分支,并将其合并回去。现在你被困住了。

GitFlow模型要求您还将修补程序也合并到开发分支,在您的情况下为“ feature1”。

因此,真正的答案将是:

git checkout feature1
git merge --no-ff hotfix1

这会将在修补程序内部进行的所有更改添加到功能分支,但仅添加那些更改。它们可能与分支中的其他开发更改冲突,但是如果最终将功能分支合并回master,则它们不会与master分支冲突。

重新定基时要非常小心。仅当您所做的更改仍位于存储库本地时(例如,您没有将任何分支推送到其他存储库),才重新设置基准。Rebasing是一个很棒的工具,可让您在将本地提交提交到世界之前将其本地排列成有用的顺序,但是事后重新打包将使像您这样的git初学者感到困惑。


7
不会。即使在合并了master和devel分支的分支名称被删除后,修复该错误的提交也只会在hotfix分支中出现一次。合并提交仅显示合并引入的更改,看起来像是重复提交。但这是git的工作方式:分支并合并回去。真正的开发工作仅在非合并提交中进行,并且仅当结果为有效软件时才接受合并。
2013年

42
这应该是公认的答案。它也与GitHub的pull request功能一起很好地工作。
Nostalg.io 2015年

125
我认为值得注意的是,a git merge master将与您的master 本地副本合并,因此,即使您git pull在别人将另一个分支合并到master中之后在功能分支中完成了a,也需要先git checkout master,然后git pull,然后git checkout feature1再然后git merge master
达米克

50
@damick Or just git fetchandgit merge origin/master
Yngvar Kristiansen

20
@damick @ yngvar-kristiansen git pull origin master将自动合并orgin/master到当前分支
L422Y

612

您应该能够基于master重新建立分支:

git checkout feature1
git rebase master

处理所有出现的冲突。当您获得带有错误修正的提交(已经在master中)时,Git会说没有任何更改,并且也许它们已经被应用。然后,您可以继续进行变基(同时跳过主数据库中已存在的提交)

git rebase --skip

如果git log在功能分支上执行,则将看到bugfix提交仅出现一次,并且出现在主部分中。

有关更详细的讨论,请参阅git rebasehttps://git-scm.com/docs/git-rebase)上的Git书文档,其中涵盖了该确切的用例。

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

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

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

将他的私人分支机构重新建立在master上正是产生此结果的原因。相反,将master合并到他的分支中将恰好完成他明确不想发生的事情:添加与他正在通过其分支进行的功能实现无关的提交。

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

  • 仅对私有分支重新设置基础(即仅存在于本地存储库中且未与其他分支共享)。重新分配共享分支机构将“破坏”其他人可能拥有的副本。
  • 如果您想将分支(主分支或另一个分支)中的更改集成到公共分支中(例如,您已推动分支打开拉取请求,但现在与主冲突,则需要更新您的分支机构来解决这些冲突),您需要将其合并(例如,与git merge master@Sven的答案中的一样)。
  • 如果您愿意,也可以将分支合并到本地私有分支中,但是请注意,这将导致分支中的“外部”提交。

最后,如果您不满意即使这个答案对@theomega来说也不是最适合您的情况的事实,则在下面添加评论不会特别有帮助:我不控制选择哪个答案,只有@theomega。


136
不,这是不安全的:如果您进行了基准调整,那么您正在更改分支的历史记录,这将影响撤消分支的开发人员。实际上,默认情况下git不会让您推送重新建立了分支的分支:当您推送使用重新建立的分支-f版本覆盖分支时,需要强制执行更新。小心!
David Sulc 2013年

17
使用git的专业团队如何处理此问题?请注意,仔细考虑然后再做-f?还是我的整个工作流程存在缺陷,因为我需要-f
theomega 2013年

30
好吧,我敢说“神圣”的规则是您不要基于(或更改提交历史)已共享的代码:这仅适用于您的本地代码。基本上,您应该在共享之前将更改重新设置为“清理”状态。在您的情况下,您可以推送一个新的,重新命名的分支(使用不同的名称),并要求同事将更改基于该分支(即,如上所述,通过将其本地分支重新构建为新分支)。然后,feature1从Github中删除。
David Sulc 2013年

19
我工作过的大多数专业团队几乎都不会使用rebase-默认情况下,它们只是合并所有内容,因此不会进行历史修改。这是我首选的工作方式。另一方面,一些团队在使用推送之前(而不是推送之后)使用rebase来“清理”提交
乔纳森·哈特利

11
是的,您永远不要为公共分支机构改组基础。但是,OP的问题似乎涉及将所做的新提交集成master到私有分支中(他提到“他的”本地分支)。在这种情况下,rebase就可以了,并且与您提到的“清理”用例相同。
David Sulc 2015年

69

根据本文,您应该:

  • 创建基于主版本的新分支

    git branch -b newmaster

  • 将您的旧功能分支合并到新分支

    git checkout newmaster

  • 解决新功能分支上的冲突

前两个命令可以组合为git checkout -b newmaster

这样,您的历史记录就很清晰,因为您不需要回溯合并。而且,您不需要非常谨慎,因为您不需要执行Git重新设置。


7
如果您使相关的git命令跟随每个点,那将很好。否则在我看来,这确实是更安全,更清洁的选择。
VirgileD '16

@zimi如果我们有一个远程分支怎么办?我们会再次重新创建新的更新功能分支吗?还是可以只设置远程上游?
Bill

@VirgileD我刚刚发布了自己的答案,并提供了更多详细信息,包括相关的git命令。
jkdev

29

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

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

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

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master




像变基一样被炒作!好老合并:)!
永远

27

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
    
  2. 切换到新分支后,请合并现有功能分支中的更改。这将添加您的提交,而不复制修补程序提交。

    git merge feature1
    
  3. 在新分支上,解决功能部件与主分支之间的所有冲突。

做完了!现在,使用新分支继续开发您的功能。


2
这样做的问题是,当需要针对master更新时,开发人员会浪费时间不断地产生新的分支。在活跃的工作中,我们可能每天要创建3个分支机构。您应该编写有关清理所有本地垃圾分支以及如何在远程上摆脱它们的说明。我们还需要有关命名所有这些分支的建议,以免引起混淆。没有这一点,这将使分支系统陷入混乱。
pauljohn32

4
您是对的,不应该一直这样做。仅当(1)您的功能需要更改master或(2)您将要与master合并分支并且可能存在冲突时。为避免混乱,可以在合并分支后将其删除。
jkdev

11

您可以使用以下脚本将master分支合并到当前分支中。

该脚本执行以下操作:

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

将此代码另存为批处理文件(.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

10

您可能可以执行“选择”操作,以将所需的确切提交拉入功能分支。

做一个git checkout hotfix1进入hotfix1分支。然后执行a,git log以获取所讨论提交的SHA-1哈希值(大序列的随机字母和数字,它们唯一标识一个提交)。复制该字符(或前10个左右的字符)。

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

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

这将把那个提交,并且只有那个提交,拉到你的功能分支中。所做的更改将在分支中-您只需“选择”即可,然后继续工作,编辑,提交,推送等内容。

最终,当您执行从一个分支到功能分支的另一次合并(反之亦然)时,Git将识别出您已经合并到其中 该特定提交中进行,知道它不必再次进行,而只是“跳过”它。


我认为这不是一个好主意。然后,IMO,此修补程序提交将真正显示在您的功能分支的历史记录中,而您基本上不需要。
马丁·佩卡

1
“最终,当您执行从一个分支到功能分支的另一次合并(反之亦然)时,git会认识到您已经合并[...]” –这实际上是如何工作的?我认为这种git merge方式在您似乎暗示的“重播提交”中不起作用(“只是跳过它”)。混合采摘和合并显然会导致问题。参见:news.ycombinator.com/item?id=3947950
Guildenstern

0

我在功能分支上进行了重构。我现在想将主更改合并到我的功能分支中。我远远落后。注意我不想将主要更改拉到本地,因为我的功能分支中的模块已从一个位置移动到另一个位置。我发现仅执行以下操作不起作用。它说“已经是最新的”。

 //below does not get the latest from remote master to my local feature branch without git pull
    git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge master

这在下面有效,请注意使用git merge origin / master:

 git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge origin/master
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.