[英]Git: rebase onto development branch from upstream
我有本地master
并develop
分支。 我做我所有的develop
工作,然后将它们合并到master
版本中。 有一个远程分支, upstream/master
,它有我想要的更改,但我想在它的更改之上重新调整我在develop
(共享一个共同祖先)中的更改并将它们放回develop
。 我已经完成了git fetch upstream
。
$ git checkout experiment
$ git rebase master
我(假设)在我的情况下意味着:
$ git checkout upstream/master
$ git rebase develop
但那时我会在upsteam/master
和超脱的头部状态。 但是,如果我合并了upstream/master
,我会从develop
进行合并,并且更改将在develop
,例如
$ git checkout develop
$ git merge upstream/master
所以这种变基的方式对我来说似乎很落后。 我想将我在develop
分支上的develop
更改重新设置为来自upstream/master
的更改,类似于合并的工作方式。 我应该在upstream/master
上做 rebase,修复任何冲突,然后添加它,把它藏起来,然后把它弹出到develop
吗?
变基实际上是:
git checkout develop
git rebase upstream/master
( git rebase
应该读作:“rebase 我当前的分支,这里是develop
,在目标分支之上,这里是upstream/master
”)
最终的结果不会是一个分离的头,而是新重写的develop
分支。
最简单(对每个人来说最明显)的方法是首先更新你的master
分支,然后 rebase 到更新的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
在这一点上,如果一切顺利, master
和origin/master
是相同的(正如您可以使用gitk
类的图形查看器或使用git log --graph --oneline --decorate
),并且应该清楚git rebase master
如何git rebase master
将工作。
但实际上您不必这样做。 你可以在develop
时git rebase origin/master
。 (这将使你的master
在某些点未进-ED-想必你会希望它前进-ED-所以它不是真正的节省您很多,但是它现在更容易做。)
冗长乏味的“为什么”部分: git rebase
在其长篇幅中包含三点,文档将其描述为newbase
、 upstream
和branch
:
git rebase ... [--onto <newbase>] [<upstream>] [<branch>]
如果您只指定一个参数,如在git rebase master
,则命名upstream
并且计算newbase
和branch
。 branch
是当前分支(即HEAD
,不得分离)。 如果省略--onto
,则将newbase
作为upstream
参数。 因此,如果您现在正在develop
,并且您运行git rebase X
,则branch
是develop
并且newbase
和upstream
都是X
。
rebase 方法实际上是(有各种内部优化,对 reflog 的影响有点不同):
branch
branch
指向的提交的引用( ORIG_HEAD
)git reset --hard
) git reset --hard
为newbase
upstream ..ORIG_HEAD
1 中的每个提交(按从旧到新的顺序), git cherry-pick
将该提交添加到刚刚重置的分支。因此,如文档中所示:
Assume the following history exists and the current branch is "topic":
A---B---C HEAD=topic
/
D---E---F---G master
当你git rebase master
你得到:
A---B---C ORIG_HEAD
/
/ A'--B'--C' HEAD=topic
/ /
D---E---F---G master
(我在这里所做的只是采用手册页中的示例并添加ORIG_HEAD
标签和HEAD=
,以显示原始提交“仍在那里”,并且HEAD
是对topic
的引用)。
那么,如果你有你的develop
和master
而他们的master
有一些额外的变化,会发生什么? 让我们画出来:
A -- B -- C master
| \
| D origin/master
|
E -- F HEAD=develop
现在你git rebase origin/master
:
A -- B -- C master
| \
| D origin/master
| \
| E' -- F' HEAD=develop
|
E -- F ORIG_HEAD
在某些时候,您最终将自己的master
也指向 commit D
(并且您删除ORIG_HEAD
)给出:
A -- B -- C -- D master, origin/master
\
E' - F' HEAD=develop
这与移动的一些标签相同。
这就是分支标签的全部内容,它们只是标签。 每个标签指向一个(单个)提交。 提交本身指向先前的提交,这就是构建提交树(或“提交 DAG”,真的)的原因。
1 Git's X .. Y
语法隐藏了很多“深奥的魔法”。 这意味着“所有提交都可以从标签Y
到达,但不能从标签X
到达。这正是需要挑选的提交集,因为那些是在branch
上的提交,而不是在upstream
,在“rebase”操作。乍一看,它“看起来像”一个基于时间的序列,这通常在人们的A..B
,但它基于提交图拓扑。但有时这会让人绊倒: A..B
,其中A
根本与B
无关(因为 repo 中有多个提交树),意味着“可以从B
访问每个修订版。
您正在寻找的命令是:
git checkout develop
git rebase upstream/master
但是,Git 比这更聪明,您可以将 upstream/master 配置为 develop 的上游跟踪分支:
git branch --set-upstream-to upstream/master develop
现在,当您执行git rebase
,它会自动使用“上游/主”。 但更好的是,这些命令:
git fetch origin
git rebase upstream/master
可以通过简单地执行以下操作来简化:
git pull --rebase
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.