【问题标题】:What is the best (and safest) way to merge a Git branch into master?将 Git 分支合并到 master 的最好(也是最安全)的方法是什么?
【发布时间】:2011-08-01 21:30:56
【问题描述】:

master 创建一个新分支,我们称之为test

有几个开发人员要么提交到master,要么创建其他分支,然后合并到master

假设test 的工作需要几天时间,而您希望通过master 内部的提交不断更新test

我会从testgit pull origin master

问题 1:这是正确的方法吗?顺便说一句,其他开发人员可以轻松地处理相同的文件。


我在test 上的工作已完成,我准备将其合并回master。以下是我能想到的两种方式:

答:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

乙:

git checkout test
git pull origin master
git checkout master
git merge test

我没有使用--rebase,因为据我了解,rebase 会从master 获取更改并将我的更改堆叠在此之上,因此它可能会覆盖其他人所做的更改。

问题 2: 这两种方法中哪一种是正确的?有什么区别?

所有这一切的目标是让我的test 分支更新master 中发生的事情,然后我可以将它们合并回master,希望尽可能保持时间线线性。

【问题讨论】:

  • no.. rebase 永远不会覆盖,它只是试图实现更清晰的历史记录。通过将历史重新附加(或伪造)到主人的后期
  • rebase 不会覆盖你的提交。它撤消您的提交,将主分支中的提交应用到您的测试分支,然后将您的提交应用回测试。
  • 如果我们没有master的写权限怎么办?有什么方法可以在功能分支上先发制人地解决冲突?我猜可能不是,因为历史可能已经分道扬镳了
  • 为什么这个问题没有结束,因为它是基于意见的?请关闭这个问题。这就是堆栈溢出的主要目的,关闭问题

标签: git git-branch git-merge branching-and-merging


【解决方案1】:

我会怎么做

git checkout master
git pull origin master
git merge test
git push origin master

如果我有一个来自远程分支的本地分支,我不喜欢将除此分支之外的其他分支与远程分支合并。此外,我不会推送我的更改,直到我对我想要推送的内容感到满意并且我根本不会推送任何东西,这仅适用于我和我的本地存储库。在您的描述中,test 似乎只适合您?所以没有理由发布它。

git 总是试图尊重你和其他人的变化,--rebase 也是如此。我认为我不能适当地解释它,所以请查看the Git book - Rebasinggit-ready: Intro into rebasing 以获得一些描述。这是一个很酷的功能

【讨论】:

  • git merge test 给了我fatal: 'test' does not point to a commit。我必须在git log 中查看测试分支上的提交点,切换回主分支然后执行git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234
  • @Duncanmoo 好吧,test 分支当然必须存在。当然,您可以改用提交哈希,但使用分支名称通常更容易。在内部它只是检索分支的HEAD 的哈希值。
  • @shanyangqu 从远程获取最新更改。如果您单独工作并且只使用一个系统,则没有问题。但是,当从不同的系统(可能来自不同的开发人员)推送更改时,一旦您尝试将合并推送回来(第 4 步),您就会看到冲突。现在唯一的解决方案是将您的本地 master 合并到远程 master 中,这最终导致一个非常丑陋的“将 master 合并到 origin/master”合并提交。因此,在合并之前拉取总是一个好主意
  • "在您的描述中,该测试似乎只适合您?所以没有理由发布它。"例如,如果该服务器提供了针对本地驱动器故障的备份,或者如果您没有其他方法进行备份,则您可能希望将本地分支推送到服务器。
  • "...另外,我不会推动我的更改,直到我对我想要推动的内容感到满意..." 为什么不推动我的改变您的代码是否已备份,以防您的本地机器死机并且几天的努力消失了?
【解决方案2】:

这是一个很实用的问题,但是上面所有的答案都不实用。

喜欢

git checkout master
git pull origin master
git merge test
git push origin master

这种方法有两个问题

  1. 不安全,因为我们不知道test分支和master分支有没有冲突。

  2. 它会将所有测试提交“挤压”到 master 上的一个合并提交中;也就是说在master分支上,我们看不到test分支的所有变更日志。

所以,当我们怀疑会有一些冲突时,我们可以进行以下 git 操作:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

commit 之前测试merge,避免--no-ff 的快进提交,

如果遇到冲突,我们可以运行git status查看冲突详情并尝试解决

git status

一旦我们解决了冲突,或者如果没有冲突,我们commitpush 他们

git commit -m 'merge test branch'
git push

但是这种方式会丢失测试分支中记录的更改历史,并且会使其他开发人员难以了解主分支的历史。

所以最好的方法是我们必须使用rebase 而不是merge(假设此时我们已经解决了分支冲突)。

以下是一个简单的示例,高级操作请参考http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

是的,当你完成了upper 之后,所有Test 分支的提交都会被移到Master 分支的头部。变基的主要好处是您可以获得线性且更清晰的项目历史记录。

你唯一需要避免的是:永远不要在公共分支上使用rebase,比如master分支。

切勿进行如下操作

git checkout master
git rebase -i test

https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing的详细信息

附录:

【讨论】:

  • 我同意重新设置测试分支以便以后合并到 master 是要走的路。即使其他答案也是正确的,这将在 master 的头部保留分支测试的变化历史,因为作者提到“你得到了一个更干净的项目”,这是版本控制系统的目的。
  • “这不是一种安全方式,因为我们不知道 test 分支和 master 分支之间是否存在任何冲突”的说法是不正确的:总是可以中止合并。即使没有冲突,只要没有推送,您始终可以撤消最后一次本地提交。如果没有正确理解 git,有些事情可能看起来有点可怕或不清楚,但“不安全”在任何方面都是不正确的。请注意不要用不正确的信息混淆他人。
  • 同意@PaulvanLeeuwen,当您将测试分支git merge 到master 中时,您将收到有关冲突的通知,这就是您将介入并合并更改的地方。完成后,您将提交合并并推回。如果您后悔或似乎无法正确合并它,您可以随时丢弃您的工作并再次从 master 中提取。所以这绝对不是不安全的..
  • 为什么要变基 -i ?
  • 变基本质上比合并更不安全。提议将变基作为更安全的合并选择是错误的。变基是一种有效的策略,但会带来更多用户应注意的警告。
【解决方案3】:

变基和合并都不应该覆盖任何人的更改(除非您在解决冲突时选择这样做)。

开发时的常用方法是

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

当你准备好合并回master时,

git checkout master
git log ..test # if you're curious
git merge test
git push

如果您担心在合并时破坏某些内容,git merge --abort 可以为您服务。

使用 push 然后 pull 作为合并的手段是愚蠢的。我也不确定你为什么将测试推向原点。

【讨论】:

  • 这个过程会增加提交的次数,每次切换分支时,都必须提交你的分支。
  • 什么?您是说每次切换分支时都会增加提交次数?还是说每次切换分支都要“提交你的分支”?第一个是不真实的,我不确定第二个是什么意思。
  • 结帐前,你必须提交分支。这就是我要说的
  • 你不知道:那是(其中一件事)git stash 是为了。
  • 或者你可以修改你的最后一次提交(在本地分支中)并在推送之前使其成为完美的提交。
【解决方案4】:

我会首先使要合并的分支尽可能干净。运行你的测试,确保状态是你想要的。清理git squash 的新提交。

除了KingCrunches answer,我建议使用

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

您可能在另一个分支中进行了多次提交,这应该只是主分支中的一次提交。为了保持提交历史尽可能干净,您可能希望将测试分支中的所有提交压缩到主分支中的一个提交中(另请参阅:Git: To squash or not to squash?)。然后,您还可以将提交消息重写为非常富有表现力的内容。无需深入研究代码即可轻松阅读和理解的内容。

编辑:你可能感兴趣

所以在 GitHub 上,我最终为功能分支 mybranch 执行以下操作:

从源头获取最新信息

$ git checkout master
$ git pull origin master

找到合并基础哈希:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

现在确保只有第一个是pick,其余的是s

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

接下来选择一个非常好的提交消息并推送到 GitHub。然后发出拉取请求。

拉取请求合并后,可以在本地删除:

$ git branch -d mybranch

在 GitHub 上

$ git push origin :mybranch

【讨论】:

  • "应该只是 master 分支中的一次提交",不一定;你可能想保留历史
  • 当然。但是不要压缩提交
  • 我认为 --first-parent 似乎是最好的解决方案。 davidchudzicki.com/posts/first-parent
【解决方案5】:

旧线程,但我还没有找到my way 这样做。对于使用 rebase 并希望在 master 之上合并来自(功能)分支的所有提交的人来说,这可能很有价值。如果途中发生冲突,您可以在每次提交时解决它们。您可以在此过程中保持完全控制,并且可以随时中止。

获取最新的 Master 和 Branch:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

在 Master 上合并分支:

git checkout <branch_name>
git rebase master

可选:如果您在变基期间遇到冲突:

首先,解决文件中的冲突。那么:

git add .
git rebase --continue

您可以随时中止变基:

git rebase --abort

推送你重新定位的分支:

git push origin <branch_name>

如果你之前推送过这个分支,你需要用强制推送覆盖它:

git push origin -f <branch_name>

在这样做之前,请始终检查您当前的本地分支是否符合您的期望,因为强制推送会覆盖远程存储库中的旧分支。

现在您有两个选择:

  • A) 创建一个 PR(例如在 GitHub 上)并通过 UI 将其合并到那里
  • B) 返回命令行,将分支合并到 master
git checkout master
git merge --no-ff <branch_name>
git push origin master

完成。

【讨论】:

  • 我也喜欢这种方式。您忘记提及的一件事是,您经常必须在 rebase 后强制推送您的
  • 已编辑。谢谢!
【解决方案6】:

这是我在团队工作中使用的工作流程。场景如你所描述。首先,当我完成 test 的工作时,我会使用 master 重新设置基础,以提取在我一直在处理 test 分支期间添加到 master 的任何内容。

git pull -r upstream master

这会将更改拉到 master,因为您创建了 test 分支并应用它们,然后应用您所做的更改以“在”当前 master 状态上进行测试。如果其他人对您在测试中编辑的相同文件进行了更改,则此处可能存在冲突。如果有,您将不得不手动修复它们并提交。完成此操作后,您最好切换到 master 分支并毫无问题地合并 test

【讨论】:

    【解决方案7】:
    git checkout master
    git pull origin master
    # Merge branch test into master
    git merge test
    

    合并后,如果文件发生了变化,那么在合并时会出现“Resolve Conflict”的错误

    那么你需要先解决所有冲突,然后你必须再次提交所有更改,然后推送

    git push origin master
    

    最好做谁在测试分支中进行了更改,因为他知道自己做了什么更改。

    【讨论】:

      【解决方案8】:

      我会使用变基方法。主要是因为它在语义上完美地反映了您的情况,即。您要做的是刷新当前分支的状态并“假装”它是基于最新的。

      所以,即使不查看 master,我会:

      git fetch origin
      git rebase -i origin/master
      # ...solve possible conflicts here
      

      当然,仅从源获取并不会刷新您的 master 的本地状态(因为它不执行合并),但对于我们的目的来说完全可以 - 我们希望避免切换,为了节省时间。

      【讨论】:

        【解决方案9】:

        @KingCrunch 的答案在许多情况下都应该有效。可能出现的一个问题是您可能在另一台需要从测试中提取最新版本的机器上。所以,我建议先拉测试。修订版如下所示:

        git checkout test
        git pull
        git checkout master
        git pull origin master
        git merge test
        git push origin master
        

        【讨论】:

          【解决方案10】:

          我会根据开发和功能分支来回答,

          如果您在功能分支上并需要使用 develop 更新它,请使用以下命令:

          git checkout develop
          git pull
          git checkout feature/xyz
          git merge develop
          

          现在您的feature/xyz 已更新为develop 分支,您可以将更改推送到远程feature/xyz

          【讨论】:

            【解决方案11】:

            正如标题所说的“最佳方式”,我认为考虑 耐心合并策略。

            发件人:https://git-scm.com/docs/merge-strategies

            使用此选项,'merge-recursive' 会花费一些额外的时间来避免有时由于不重要的匹配行(例如,来自不同函数的大括号)而发生的错误合并。当要合并的分支大相径庭时使用此选项。另见 git-diff[1] --patience。

            用法:

            git fetch
            git merge -s recursive -X patience origin/master
            

            Git 别名

            我总是为此使用别名,例如运行一次:

             git config --global alias.pmerge 'merge -s recursive -X patience'
            

            现在你可以这样做了:

            git fetch
            git pmerge origin/master
            

            【讨论】:

              【解决方案12】:

              我在只做git merge feature-branch 时总是遇到合并冲突。这似乎对我有用:

              git checkout -b feature-branch
              

              做一堆代码更改...

              git merge -s ours master 
              
              git checkout master
              
              git merge feature-branch
              

              git checkout -b feature-branch
              

              做一堆代码更改...

              git checkout master
              
              git merge -X theirs feature-branch
              

              【讨论】:

                【解决方案13】:

                你必须签出分支才能拉取,因为拉取意味着合并到master,你需要一个工作树来合并。

                git checkout master
                git pull
                

                无需先结账; rebase 用两个参数做正确的事

                git rebase master test  
                
                git checkout master
                git merge test
                

                git push 默认推送这里和远程存在的所有分支

                git push
                git checkout test
                

                【讨论】:

                  【解决方案14】:

                  这是来自 GitLab: 只需按照说明操作:

                  【讨论】:

                  • step-1 中,您正在检出一些功能分支,然后在step-2 中,您再次检出主分支。我很困惑,为什么要首先检查功能分支?请解释
                  • 这是因为在这种情况下,它首先从原始(远程)“功能”分支获取。之后,为了将“功能”合并到“主”,您需要签出“主”并将“功能”合并到它。
                  • 那么在第一种情况下,git fetch origin feature 不应该是检查远程功能分支以同步本地与远程功能后的第二个命令?
                  【解决方案15】:

                  这里已经有很多很好的答案了。我只是添加我所做的步骤。

                  git fetch -p
                  git checkout master
                  git rebase origin/master
                  git checkout test
                  git rebase master
                  

                  解释

                  git fetch -p 将检索自您上次提取以来所做的任何更改,-p 修剪您的分支,删除所有过时的分支。

                  git checkout master检查主分支

                  git rebase origin/master 更新 master 分支。在这里拉动会得到相同的结果。

                  git checkout test签出你所做更改的分支

                  git rebase mastermaster 上的更改更新test 分支。这会合并所有更改的文件,如果您的任何提交存在冲突,您必须解决它们,然后执行 git rebase --continuegit rebase --abort

                  【讨论】:

                    猜你喜欢
                    • 2012-03-03
                    • 2011-04-14
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-04-30
                    • 2020-08-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多