Git:从上游变基到开发分支

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19200561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 09:09:33  来源:igfitidea点击:

Git: rebase onto development branch from upstream

git

提问by iain

I have local masterand developbranches. I do all my work on developand then merge them into masterfor releases. There is a remote branch, upstream/masterwhich has changes I want, but I want to rebase my changes in develop(which shares a common ancester) on top of its changes and put them back into develop. I've already done git fetch upstream.

我有本地masterdevelop分支机构。我做我所有的工作develop,然后将它们合并到master版本中。有一个远程分支,upstream/master它有我想要的更改,但我想将我的更改develop(共享一个共同的祖先)基于其更改,并将它们放回develop. 我已经做了git fetch upstream

The Git book chapter on rebasingsays to do:

关于 rebaseGit 书籍章节说要这样做:

$ git checkout experiment
$ git rebase master

Which I (assume) in my case would mean:

我(假设)在我的情况下意味着:

$ git checkout upstream/master
$ git rebase develop

But then I'd be on the upsteam/masterand in detached head state. However, if I did a merge of upstream/master, I'd do that from develop, and the changes would be on develop, e.g.

但那时我会upsteam/master处于超然状态。但是,如果我合并了upstream/master,我会从 开始develop,并且更改将在develop,例如

$ git checkout develop
$ git merge upstream/master

So this way to rebase seems backward to me. I'd like to rebase my changes in developon the developbranch with the changes from upstream/mastersimilar to how the merge would work. Am I supposed to do the rebase on upstream/master, fix any conflicts, and then add it, stash it and pop it onto develop?

所以这种变基的方式对我来说似乎很落后。我想变基在我的变化developdevelop从变化的分支upstream/master类似合并将如何工作。我是否应该在 上进行变基upstream/master,修复任何冲突,然后添加它,将其隐藏并弹出到 上develop

Hopefully this makes sense and someone can help me with this, it would be gratefully appreciated.

希望这是有道理的,有人可以帮助我解决这个问题,将不胜感激。

采纳答案by VonC

The rebase would actually be:

变基实际上是:

git checkout develop
git rebase upstream/master

(git rebaseshould read: "rebase my current branch, here develop, on top oftarget branch, here upstream/master")

git rebase应该读作:“rebase 我当前的分支,在这里develop目标分支的顶部,在这里upstream/master”)

And the end result wouldn't be a detached head, but the newly rewritten developbranch.

最终的结果不会是一个分离的头,而是新重写的develop分支。

回答by torek

The simplest (most obvious to everyone) method is to update your masterbranch first, then rebase onto the updated masterwhich is now exactly the same as origin/master:

最简单(对每个人来说最明显)的方法是首先更新您的master分支,然后重新建立在更新的分支上,master现在与以下完全相同origin/master

$ git fetch origin                    # Get updates from remote.
$ git checkout master                 # Now bring master into sync:
$ git merge --ff-only origin/master   # if this fails you have stuff
                                      # in your master that they don't
                                      # have in theirs, and you need
                                      # to decide what to do about it

At this point, if all went well, masterand origin/masterare the same (as you can see with graphical viewers like gitk, or with git log --graph --oneline --decorate), and it should be clear how git rebase masterwill work.

在这一点上,如果一切顺利,master并且origin/master是相同的(正如您可以在图形查看器中看到的,例如gitk, 或git log --graph --oneline --decorate),那么将如何git rebase master工作应该很清楚了。

But you don't actually have to do that. You can just git rebase origin/master, while being on develop. (This will leave your masterun-forward-ed—presumably at some point you will want it forward-ed—so it's not really saving you much. But it iseasier to do now.)

但实际上您不必这样做。你可以git rebase origin/master,而在develop。(这将使您master未进-ED-可能在某些时候,你会希望它前进-ED-所以它不是真正的节省您很多,但是它现在容易的事情。)



The long boring "why" part: git rebasetakes, in its long form, three points, which the documentation describes as newbase, upstream, and branch:

长期枯燥的“为什么”的一部分:git rebase需要,在其漫长的形式,三个点,该文档描述为newbaseupstreambranch

git rebase ... [--onto <newbase>] [<upstream>] [<branch>]

If you specify exactly one argument, as in git rebase master, that names the upstreamand both newbaseand branchare computed. The branchis the current branch (i.e., HEAD, which must not be detached). If you omit --onto, the newbaseis taken as the upstreamargument. So if you're on developnow, and you run git rebase X, the branchis developand both newbaseand upstreamare X.

如果您指定只有一个参数,如git rebase master,名称的upstream无一不newbasebranch计算。该branch是当前分支(即HEAD,它不能脱离)。如果省略--onto,则将newbase其作为upstream参数。因此,如果您现在打开develop并运行git rebase X,则branchisdevelop和 bothnewbaseupstreamare X

The rebase method is, in effect (there are various internal optimizations and the effect on the reflog is a bit different):

rebase 方法实际上是(有各种内部优化,对 reflog 的影响有点不同):

  1. check out branch
  2. save a reference (ORIG_HEAD) to the commit to which branchpoints
  3. reset it (a la git reset --hard) to newbase
  4. for every commit in upstream..ORIG_HEAD1(in oldest to newest order), git cherry-pickthat commit to add it to the just-reset branch.
  1. 查看 branch
  2. 保存的参考(ORIG_HEAD)到提交到branch
  3. 将它(a la git reset --hard)重置为newbase
  4. 对于upstream..ORIG_HEAD1 中的每个提交(按最旧到最新的顺序),git cherry-pick该提交将其添加到刚刚重置的分支。

Thus, as in the documentation:

因此,如文档中所示:

   Assume the following history exists and the current branch is "topic":

                 A---B---C  HEAD=topic
                /
           D---E---F---G    master

when you git rebase masteryou get:

git rebase master你得到:

                   A---B---C         ORIG_HEAD
                  /
                 /       A'--B'--C'  HEAD=topic
                /       /
           D---E---F---G             master

(all I did here was take the example in the man page and add the ORIG_HEADlabel and the HEAD=, to show that the original commits are "still in there", and that HEADis a reference to topic).

(我在这里所做的只是采用手册页中的示例并添加ORIG_HEAD标签和HEAD=, 以表明原始提交“仍在那里”,这HEAD是对 的引用topic)。

So, what happens if you have your developand masterand they have their masterwhich has a few extra changes in it? Let's draw that:

那么,如果你有你的developmaster他们有他们的master其中有一些额外的变化会发生什么?让我们画出来:

A -- B -- C                         master
          | \
          |   D                     origin/master
          |
          E -- F                    HEAD=develop

Now you git rebase origin/master:

现在你git rebase origin/master

A -- B -- C                         master
          | \
          |   D                     origin/master
          |     \
          |       E' -- F'          HEAD=develop
          |
          E -- F                    ORIG_HEAD

At some point, you eventually move your own masterto point to commit Dtoo (and you drop ORIG_HEAD) giving:

在某些时候,您最终也将自己master的指向提交D(并且您放弃ORIG_HEAD)给出:

A -- B -- C -- D                    master, origin/master
                 \
                   E' - F'          HEAD=develop

which is the same thing with some of the labels moved around.

这与移动的一些标签相同。

That's all that the branch labels are, they are just labels. Each label points to one (single) commit. The commits themselves point back to previous commits, which is what builds the commit tree (or "commit DAG", really).

这就是分支标签的全部内容,它们只是标签。每个标签指向一个(单个)提交。提交本身指向以前的提交,这就是构建提交树(或“提交 DAG”,真的)的原因。



1Git's X..Ysyntax hides a lot of "deep magic". It means "all commits reachable from label Ythat are not reachable from label X. Which is exactly the set of commits that need to be cherry-picked, as those are the commits that were on branch, and were not on upstream, before the "rebase" op. It "looks like" a time-based sequence at first blush, and that generally works in people's heads, but it's based on the commit graph topology. Sometimes this trips people up though: A..B, where Ais not related to Bat all (because of multiple commit trees in the repo), means "every revision reachable from B.

1语法隐藏了很多“深奥的魔法”。这意味着“所有提交都可以从 label 到达,但不能从 label 到达。这正是需要精心挑选的提交集,因为那些是在“rebase”操作之前在上和不在 上的提交. 乍一看,它“看起来像”一个基于时间的序列,这通常在人们的脑海中起作用,但它基于提交图拓扑。但有时这会让人们感到困惑:, where根本不相关(因为存储库中的多个提交树),意味着“从.Git's X..YYXbranchupstreamA..BABB

回答by FelipeC

The command you are looking for is:

您正在寻找的命令是:

git checkout develop
git rebase upstream/master

However, Git is smarter than that, you can configure upstream/master as the upstream tracking branch of develop:

但是,Git 比这更聪明,您可以将 upstream/master 配置为 develop 的上游跟踪分支:

git branch --set-upstream-to upstream/master develop

Now when you do git rebase, it would automatically use 'upstream/master'. But even better, these commands:

现在,当您这样做时git rebase,它会自动使用“上游/主”。但更好的是,这些命令:

git fetch origin
git rebase upstream/master

Can be simplified by simply doing:

可以通过简单地执行以下操作来简化:

git pull --rebase