【问题标题】:Git merge hotfix branch into feature branchGit 将修补程序分支合并到功能分支中
【发布时间】:2013-06-02 02:25:06
【问题描述】:

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

  1. 已创建的存储库:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. master 中的一些修改发生并被提交:

    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. 功能 1 的开发仍在继续:

    git checkout feature1
    

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

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

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

【问题讨论】:

  • 如果分支feature1 完全是本地的,请查看git rebase
  • 谢谢,作为一个 git 初学者,git rebase 对我来说就像是黑魔法......
  • 如果分支是 feature-只有错误修复不应该在那里发生(至少如果不是阻塞错误),因为这个分支的目的是显示一个新的特征。当与存在修复提交的主节点合并时,该错误将得到修复。
  • 对于初学者来说可能值得注意的是,在 3.git branch feature1git checkout feature1 可以合并为 git checkout -b feature1 和 4. 可以完全简化为 git checkout -b hotfix1 master
  • 您愿意回来更改接受的答案吗,因为当前接受的答案很糟糕。

标签: git git-branch git-merge git-flow feature-branch


【解决方案1】:

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

git checkout feature1
git merge master

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

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

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

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

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

所以真正的答案是:

git checkout feature1
git merge --no-ff hotfix1

这会将在修补程序中所做的所有更改添加到功能分支,但这些更改。它们可能会与分支中的其他开发更改发生冲突,但如果您最终将功能分支合并回主分支,它们不会与主分支冲突。

在变基时要非常小心。仅当您所做的更改保留在您的存储库本地时才重新设置基准,例如您没有将任何分支推送到其他存储库。变基是一个很好的工具,可以让您在将本地提交发布到世界之前将其安排成有用的顺序,但是之后的变基对于像您这样的 git 初学者来说会搞砸事情。

【讨论】:

  • 没有。修复 bug 的提交只在 hotfix 分支中出现一次,即使分支名称在合并到 master 和 devel 分支后被删除。合并提交只显示合并引入的更改,看起来像重复提交。但这就是 git 的工作方式:分支并合并回来。真正的开发工作只发生在非合并提交中,只有当结果是工作软件时才接受合并。
  • 这应该是公认的答案。它也适用于 GitHub 的拉取请求功能。
  • 我认为值得注意的是 git merge master 将从您的 本地 master 副本中合并,因此即使您在之后的功能分支中完成了 git pull其他人将不同的分支合并到 master 中,您需要 git checkout master,然后是 git pull,然后是 git checkout feature1,然后是 git merge master
  • @damick 或者只是 git fetchgit merge origin/master
  • @damick @yngvar-kristiansen git pull origin master 会自动将orgin/master 合并到当前分支
【解决方案2】:

您应该能够在 master 上重新设置您的分支:

git checkout feature1
git rebase master

管理出现的所有冲突。当您进行带有错误修复的提交时(已经在 master 中),Git 会说没有更改,并且可能已经应用了它们。然后你继续 rebase(同时跳过已经在 master 中的提交)

git rebase --skip

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

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

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

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

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

将他的私有分支重新建立在 master 上正是产生该结果的原因。相比之下,将 master 合并到他的分支中会准确地做他特别不希望发生的事情:添加一个与他正在处理的功能实现无关的提交他的分支。

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

  • 仅 rebase 私有分支(即仅存在于您的本地存储库中并且尚未与其他人共享)。重新设置共享分支会“破坏”其他人可能拥有的副本。
  • 如果您想将来自一个分支(无论是主分支还是另一个分支)的更改集成到一个公开的分支中(例如,您已推送分支以打开拉取请求,但现在与主分支发生冲突,并且您需要更新您的分支以解决这些冲突)您需要将它们合并(例如git merge master,如@Sven 的回答)。
  • 如果您愿意,也可以将分支合并到本地私有分支中,但请注意,这会导致分支中出现“外部”提交。

最后,如果您不满意这个答案不是最适合您的情况,即使它适用于@theomega,在下面添加评论也不会特别有帮助:我无法控制哪个答案被选中,只有 @theomega 会。

【讨论】:

  • 不,这不安全:如果你变基,你正在改变分支的历史,这将影响到拉分支的开发者。 inf 行为,git 默认情况下不会让您推送重新定位的分支:您需要在推送以使用重新定位的版本覆盖分支时使用 -f 强制更新。小心!
  • 使用git的专业团队如何处理这个问题?只是注意,仔细考虑然后做一个-f?还是因为我需要 -f 而导致我的整个工作流程存在缺陷?
  • 好吧,我敢冒险“神圣”的规则是你不要基于已共享的代码(或以其他方式更改提交历史):它只适用于你的本地代码。基本上,您应该在共享之前将您的更改重新设置为“清理”。在您的情况下,您可以推送一个新的 rebase 分支(使用不同的名称),并要求同事将他们的更改基于该分支(即,通过将他们的本地分支 rebase 来自新分支,如上所述)。然后,从 Github 中删除 feature1
  • 我工作过的大多数专业团队几乎从不使用 rebase - 他们只是默认合并所有内容,因此不会发生历史修改。这是我首选的工作方式。另一方面,一些团队在推送之前使用 rebase 来“清理”提交(但在推送之后从不。)
  • 如果您能详细说明为什么您认为这是一个糟糕的想法,那就太好了:git 文档特别给出了这些作为示例使用 rebase git-scm.com/docs/git-rebase 很明显,您不应该重新设置公众的基础/shared 分支,但使用它来重写/清理私有分支上的历史记录(包括将其更新为分支master)很好:这正是私有分支存在的原因。说rebase 命令是为那些犯错或不了解 DVCS 的人准备的,这对我来说似乎有点误导。
【解决方案3】:

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分支,master是本地master分支

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master

【讨论】:

  • 感觉 rebase 被炒作了!好旧的合并:)!
  • 从另一个答案尝试git merge master 并获得Already up to date。您的回答有助于了解我在当地有老主人。谢谢!
  • 我在我的分支上执行 1.git merge master。我的分支是本地和远程的。但是在git merge master 之后,我总是在我的分支中看到来自 master 的所有新更改/提交。当我创建 PR 时,它会显示所有文件 = 我的更改 + 其他来自 master 的更改。我做错了吗?
【解决方案4】:

基于this article,您应该:

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

    git branch -b newmaster

  • 将旧功能分支合并到新功能分支中

    git checkout newmaster

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

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

这样您的历史记录就会保持清晰,因为您不需要反向合并。而且你不需要这么小心,因为你不需要做一个 Git rebase。

【讨论】:

  • 如果你让相关的 git 命令跟随每一点会很好。否则在我看来,这确实是更安全、更干净的选择。
  • @zimi 如果我们有一个远程分支怎么办?我们会重新创建新的更新功能分支吗?或者我们可以只设置远程上游?
  • @VirgileD 我刚刚发布了my own answer 的更多详细信息,包括相关的 git 命令。
【解决方案5】:

Zimi's answer 概括地描述了这个过程。具体如下:

  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. 在新分支上,解决您的功能与主分支之间的任何冲突。

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

【讨论】:

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

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

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

假设我有一个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 

我希望这对处于相同情况的其他人有所帮助。

【讨论】:

  • 您从哪个文件夹执行 git checkout master?从分支文件夹?
  • @JoseCabreraZuniga,我是从您存储库的根文件夹中完成的。
【解决方案7】:

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

脚本执行以下操作:

  • 切换到主分支
  • 拉出主分支
  • 切换回当前分支
  • 将 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

【讨论】:

    【解决方案8】:

    您也许可以进行“挑选”以将所需的准确提交拉入功能分支。

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

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

    那么,git cherry-pick <the SHA-1 hash that you just copied>

    这会将那个提交,并且那个提交,拉到你的特性分支中。该更改将在分支中 - 您只是“挑选”它。然后,恢复工作、编辑、提交、推送等,让您心满意足。

    最终,当您从一个分支执行另一次合并到您的功能分支(反之亦然)时,Git 会识别出您已经在 那个特定的提交中合并,知道它没有不必再做一次,只需“跳过”它。

    【讨论】:

    • 我认为这不是一个好主意。然后,IMO,修补程序提交将真正显示在您的功能分支的历史记录中,这基本上是您不想要的。
    • “当你最终从一个分支执行另一次合并到你的特性分支(反之亦然)时,git 会识别出你已经合并了 [...]”——这就是如何它真的有效吗?我不认为git merge 以这种“重放提交”的方式工作——你似乎暗示要这样做(“跳过它”)。混合樱桃采摘和合并显然会导致问题;见:news.ycombinator.com/item?id=3947950
    【解决方案9】:

    补充现有答案,因为这些命令是经常性的,我们可以连续执行。鉴于我们在功能分支中:

    git checkout master && git pull && git checkout - && git merge -
    

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

    alias merge_with_master="git checkout master && git pull && git checkout - && git merge -"
    

    【讨论】:

      【解决方案10】:

      我在功能分支上进行了重构。我现在想将主更改合并到我的功能分支。我远远落后。 注意我不想将主更改拉到我的本地,因为我的功能分支已将模块从一个地方移动到另一个地方。我发现在没有拉的情况下只在下面执行是行不通的。它说“已经是最新的。”

       //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
      

      【讨论】:

        【解决方案11】:

        要开始对大文件进行版本控制,您只需执行以下简单步骤: 为您的操作系统下载并安装 Git LFS 命令行扩展。 为您的用户帐户设置 Git LFS: git lfs 安装 3. 配置 Git LFS 来跟踪你的大文件: git lfs 跟踪“*.xyz”

        【讨论】:

        • 这个答案没有意义。他们没有问任何关于大文件的问题。
        【解决方案12】:
        In Eclipse -
        

        1)结帐主分支

        Git Repositories ->Click on your repository -> click on Local ->double click master branch
        ->Click on yes for check out
        

        2)拉主分支

        Right click on project ->click on Team -> Click on Pull
        

        3)检查您的功能分支(按照 1 点中提到的相同步骤)

        4)将master合并到feature中

        Git Repositories ->Click on your repository -> click on Local ->Right Click on your selected feature branch ->Click on merge ->Click on Local ->Click on Master ->Click on Merge.
        

        5) 现在您将在功能分支中获得 Master 分支的所有更改。如果有冲突,请删除。

        For conflict if any exists ,follow this -
        Changes mentioned as Head(<<<<<< HEAD) is your change, Changes mentioned in branch(>>>>>>> branch) is other person change, you can update file accordingly.
        

        注意 - 您需要为冲突文件添加索引

        6) 在功能分支中提交并推送您的更改。

        Right click on project ->click on Team -> Click on commit -> Commit and Push.
        

        Git Repositories ->Click on your repository -> click on Local ->Right Click on your selected feature branch ->Click on Push Branch ->Preview ->Push
        

        【讨论】:

          猜你喜欢
          • 2013-02-21
          • 1970-01-01
          • 2012-05-08
          • 2012-06-01
          • 1970-01-01
          • 2021-01-12
          • 2013-12-05
          • 2015-11-18
          • 2016-03-20
          相关资源
          最近更新 更多