Hg:如何像 git 的 rebase 一样进行 rebase
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2672351/
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
Hg: How to do a rebase like git's rebase
提问by jpswain
In Git I can do this:
在 Git 中,我可以这样做:
1. Start working on new feature: $ git co -b newfeature-123 # (a local feature development branch) do a few commits (M, N, O) master A---B---C \ newfeature-123 M---N---O 2. Pull new changes from upstream master: $ git pull (master updated with ff-commits) master A---B---C---D---E---F \ newfeature-123 M---N---O 3. Rebase off master so that my new feature can be developed against the latest upstream changes: (from newfeature-123) $ git rebase master master A---B---C---D---E---F \ newfeature-123 M---N---O
I want to know how to do the same thing in Mercurial, and I've scoured the web for an answer, but the best I could find was: git rebase - can hg do that
我想知道如何在 Mercurial 中做同样的事情,我已经在网上搜索了答案,但我能找到的最好的是:git rebase - can hg do that
That link provides 2 examples:
1. I'll admit that this: (replacing the revisions from the example with those from my own example)
该链接提供了 2 个示例:
1. 我承认这一点:(将示例中的修订替换为我自己示例中的修订)
hg up -C F hg branch -f newfeature-123 hg transplant -a -b newfeature-123
is not too bad, except that it leaves behind the pre-rebase M-N-O as an unmerged head and creates 3 new commits M',N',O' that represent them branching off the updated mainline.
还不错,除了它将预变基 MNO 作为未合并的负责人留下并创建 3 个新提交 M',N',O' 代表它们从更新的主线分支。
Basically the problem is that I end up with this:
基本上问题是我最终得到了这个:
master A---B---C---D---E---F \ \ newfeature-123 \ M'---N'---O' \ newfeature-123 M---N---O
this is not good because it leaves behind local, unwanted commits that should be dropped.
这不好,因为它留下了应该删除的本地、不需要的提交。
- The other option from the same link is
- 来自同一链接的另一个选项是
hg qimport -r M:O hg qpop -a hg up F hg branch newfeature-123 hg qpush -a hg qdel -r qbase:qtip
and this does result in the desired graph:
这确实会产生所需的图形:
master A---B---C---D---E---F \ newfeature-123 M---N---O
but these commands (all 6 of them!) seem so much more complicated than
但是这些命令(全部 6 个!)似乎比
$ git rebase master
I want to know if this is the only equivalent in Hg or if there is some other way available that is simple like Git.
我想知道这是否是 Hg 中唯一的等价物,或者是否有其他一些像 Git 这样简单的可用方法。
回答by Ry4an Brase
VonC has the answer you're looking for, the Rebase Extension. It is, however, worth spending a second or two thinking about why neither mq nor rebase are enabled by default in mercurial: because mercurial is all about indelible changesets. When I work in the manner you're describing, which is nearly daily, here's the pattern I take:
VonC 有您正在寻找的答案,即 Rebase 扩展。然而,值得花一两秒钟思考为什么在 mercurial 中默认情况下既不启用 mq 也不启用 rebase:因为 mercurial 都是关于不可磨灭的变更集。当我以您所描述的方式工作时,几乎每天都有,这是我采用的模式:
1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)
master A---B---C
\
newfeature-123 M---N---O
2. Pull new changes from upstream mainline:
$ hg pull
master A---B---C---D---E---F
\
newfeature-123 M---N---O
3. merge master into my clone so that my new feature
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F
master A---B---C---D---E---F
\ \
newfeature-123 M---N---O---P
and that's really all that's necessary. I end up with a newfeature-123 clone I can easily push back to the mainline when I'm happy with it. Most importantly, however, I never changed history. Someone can look at my csets and see what they were originally coded against and how I reacted to changes in the mainline throughout my work. Not everyone thinks that has value, but I'm a firm believer that it's the job of source control to show us not what we wished had happened, but what actually happened -- every deadend and every refactor should leave an indelible trace, and rebasing and other history editing techniques hide that.
这就是真正需要的。我最终得到了一个 newfeature-123 克隆,当我对它感到满意时,我可以轻松地将其推回主线。然而,最重要的是,我从未改变过历史。有人可以查看我的 cset,看看它们最初是根据什么编码的,以及我对整个工作中主线变化的反应。不是每个人都认为这有价值,但我坚信源代码控制的工作不是向我们展示我们希望发生的事情,而是实际发生的事情——每一个死胡同和每一次重构都应该留下不可磨灭的痕迹,并重新定位和其他历史编辑技术隐藏了这一点。
Now go pick VonC's answer while I put my soapbox away. :)
现在去选择 VonC 的答案,而我把肥皂盒收起来。:)
回答by VonC
You might be looking for Rebase Extension. (implemented as part of the SummerOfCode 2008)
您可能正在寻找Rebase Extension。(作为SummerOfCode 2008 的一部分实施)
In those cases it can be useful to "detach" the local changes, synchronize the repository with the mainstream and then append the private changes on top of the new remote changes. This operation is called rebase.
在这些情况下,“分离”本地更改,将存储库与主流同步,然后将私有更改附加到新的远程更改之上会很有用。此操作称为变基。
从:
to:
到:
As commented belowby steprobe:
In the case where you aren't pulling the changes in, and you have the two branches in your repo, you can do (using
keepbranches
):
如果您没有提取更改,并且您的存储库中有两个分支,您可以执行以下操作(使用
keepbranches
):
hg up newfeature-123
hg rebase -d master --keepbranches
(--keepbranches
: Inherit the original branch name.)
( --keepbranches
: 继承原来的分支名称。)
Mojcamentions:
莫伊卡提到:
I like using
hg rebase --source {L1's-sha} --dest {R2's-sha}
, but I didn't know I could add--keepbranches
at the end.
我喜欢使用
hg rebase --source {L1's-sha} --dest {R2's-sha}
,但我不知道我可以--keepbranches
在最后添加。
As illustrated belowby Jonathan Blackburn:
hg rebase -d default --keepbranches
回答by sblom
Assuming you have a modern Hg installation, you can simply add:
假设你有一个现代 Hg 安装,你可以简单地添加:
[extensions]
rebase =
to ~/.hgrc.
到 ~/.hgrc。
Then you can use the commands hg rebase
, hg pull --rebase
, or hg help rebase
.
然后您可以使用命令hg rebase
、hg pull --rebase
、 或hg help rebase
。
回答by Jonathan Blackburn
I don't think the answers above achieve the OP's goal, which was to maintain his task branch, just rebased against a later point on the parent branch.
我认为上面的答案没有实现 OP 的目标,即维护他的任务分支,只是根据父分支的稍后点重新定位。
Let's say I start with this graph (generated using the graphlog extension. Serious geek love for graphlog).
假设我从这个图开始(使用 graphlog 扩展生成。对 graphlog 的狂热爱好者)。
@ 9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o af630ccb4a80 default againagainagain
| |
o | 98bdde5d2185 Feature 3 branch commit 1 feature3
|/
o e9f850ac41da foo
If I'm on the feature3 branch and want to rebase it off of the againagainagain commit, I understand that I would run hg rebase -d default
. This has the following result:
如果我在 feature3 分支上并想将它从再次提交中重新设置为基准,我知道我会运行hg rebase -d default
. 这有以下结果:
@ 89dada24591e Feature 3 commit 2 tip
|
o 77dcce88786d Feature 3 branch commit 1
|
o af630ccb4a80 default againagainagain
|
o e9f850ac41da foo
Mission accomplished? I don't think so. The problem is that when the commits on the feature3 branch were rebased on againagainagain, the feature3 branch was deleted. My commits have been moved to the default branch, which was what I was trying to avoid in the first place.
任务完成?我不这么认为。问题是,当 feature3 分支上的提交再次重新基于再次重新构建时,feature3 分支被删除了。我的提交已移至默认分支,这是我首先试图避免的。
In Git, the result would look like this:
在 Git 中,结果如下所示:
@ 9a4c0eb66429 Feature 3 commit 2 tip
|
o 98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o af630ccb4a80 default againagainagain
|
o e9f850ac41da foo
Notice that the feature3 branch still exists, the two commits are still on the feature3 branch, and not visible on default. Without preserving the task branch, I don't see how this is functionally different from a merge.
请注意,feature3 分支仍然存在,两次提交仍然在 feature3 分支上,默认情况下不可见。如果不保留任务分支,我看不出这与合并在功能上有何不同。
UPDATE: I discovered the --keepbranches
flag supported by hg rebase, and I'm happy to report everything is okey-dokey. Using hg rebase -d default --keepbranches
, I exactly replicate the Git behavior I craved. A couple of aliases later and I'm rebasing like nobody's business.
更新:我发现了--keepbranches
hg rebase 支持的标志,我很高兴地报告一切都是 okey-dokey。使用hg rebase -d default --keepbranches
,我完全复制了我渴望的 Git 行为。几个别名之后,我正在变基,就像没人管一样。
回答by Peter Cordes
Since some people have chimed in saying they think it's good to keep every iteration of everything, I'll point out that for larger open-source projects, accepting changes full of merges and development iteration would make for a messy mainline revision history, and make the revision history less useful for seeing how the current version got there.
由于有些人表示他们认为保留所有内容的每次迭代都很好,因此我要指出,对于较大的开源项目,接受充满合并和开发迭代的更改会导致主线修订历史变得混乱,并且修订历史对于查看当前版本如何到达那里不太有用。
This works well when submitted changes are reviewed by people that didn't write them, before they're accepted, so changes that do go into the mainline are generally debugged and working. Then when you backtrack to the origin of a line, you see all the changes that go with it, not some point in the middle of development of the change it's part of.
当提交的更改在被接受之前由没有编写它们的人进行时,这很有效,因此进入主线的更改通常会被调试和工作。然后,当您回溯到一条线的原点时,您会看到随之而来的所有变化,而不是它所属的变化的发展过程中的某个点。
The x265 contributorspage explains how to re-commit a set of changes you're working on, to get them ready for submissionto the x265 project. (Including use of TortoiseHG to commit some but not all changes in an individual file, like git gui's stage/unstage diff hunk for commit).
在X265贡献者页解释了如何重新提交了一组正在努力改变的,让他们准备提交到X265的项目。(包括使用 TortoiseHG 在单个文件中提交一些但不是全部的更改,例如用于提交的 git gui 的 stage/unstage diff 大块)。
The process is to get hg updated to the upstream tip, and then get all your changes uncommitted in the working directory. Shelve any that aren't part of what you want to submit, then break the rest into as many separate commits are appropriate, with nice commit messages.
该过程是将 hg 更新到上游提示,然后在工作目录中取消提交所有更改。搁置任何不属于您要提交的内容,然后将其余部分分解为许多合适的单独提交,并带有漂亮的提交消息。
I guess you'd copy/paste and then edit commit messages from previous iterations of a patchset that you're revising. Or maybe you could graft your old commits (cherry-pick in git language), and then amend them one by one, to get your old commit messages as a start point for editting.
我猜您会复制/粘贴然后编辑来自您正在修改的补丁集的先前迭代的提交消息。或者你可以嫁接旧的提交(git 语言中的cherry-pick),然后一一修改,以获取旧的提交消息作为编辑的起点。