210

在 Git 中,我可以这样做:

1.开始开发新功能:
$ git co -b newfeature-123 #(本地功能开发分支)
做一些提交(M,N,O)

大师A---B---C
                \
新功能-123 M---N---O

2. 从上游 master 拉取新的变化:
$ git拉
(master 用 ff-commits 更新)

主 A---B---C---D---E---F
                \
新功能-123 M---N---O

3. rebase off master 让我的新功能
可以针对最新的上游更改进行开发:
(来自 newfeature-123)
$ git rebase master

主 A---B---C---D---E---F
                            \
新功能-123 M---N---O


我想知道如何在 Mercurial 中做同样的事情,我已经在网上搜索了答案,但我能找到的最好的是:git rebase - can hg do that

该链接提供了 2 个示例:
1. 我承认这一点:(将示例中的修订替换为我自己示例中的修订)

汞上升-CF  
hg 分支 -f newfeature-123  
hg 移植 -a -b newfeature-123

还不错,除了它将 pre-rebase MNO 作为未合并的头部留下并创建 3 个新提交 M',N',O' 代表它们从更新的主线分支。

基本上问题是我最终得到了这个:

主 A---B---C---D---E---F
                \ \
新功能-123 \ M'---N'---O'
                  \
新功能-123 M---N---O

这不好,因为它留下了应该删除的本地不需要的提交。

  1. 来自同一链接的另一个选项是
hg qimport -r M:O
hg qpop -a
hg起来F
HG 分支 newfeature-123
hg qpush -a
hg qdel -r qbase:qtip

这确实会产生所需的图表:

主 A---B---C---D---E---F
                            \
新功能-123 M---N---O

但是这些命令(全部 6 个!)似乎比

$ git rebase master

我想知道这是否是 Hg 中唯一的等价物,或者是否有其他可用的方法,比如 Git。

4

5 回答 5

237

VonC 有您正在寻找的答案,即 Rebase Extension。然而,值得花一两秒钟思考为什么在 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

这就是真正需要的。我最终得到了一个 newfeature-123 克隆,当我对它感到满意时,我可以轻松地推回主线。然而,最重要的是,我从未改变历史。有人可以查看我的 cset 并查看它们最初是针对什么进行编码的,以及我在整个工作过程中对主线中的变化有何反应。不是每个人都认为这是有价值的,但我坚信源代码控制的工作不是向我们展示我们希望发生的事情,而是向我们展示实际发生的事情——每一个死胡同和每一个重构都应该留下不可磨灭的痕迹,并重新定位和其他历史编辑技术隐藏了这一点。

现在,当我把我的肥皂盒收起来的时候,去挑选 VonC 的答案。:)

于 2010-04-20T04:14:15.697 回答
105

您可能正在寻找Rebase Extension。(作为SummerOfCode 2008的一部分实施)

在这些情况下,“分离”本地更改,将存储库与主流同步,然后将私有更改附加到新的远程更改之上会很有用。此操作称为变基。

来自

替代文字

到:

替代文字


正如steprobe在下面评论的那样:

如果您没有拉入更改,并且您的仓库中有两个分支,您可以这样做(usingkeepbranches):

hg up newfeature-123 
hg rebase -d master --keepbranches

( --keepbranches: 继承原来的分支名称。)

Mojca提到:

我喜欢使用hg rebase --source {L1's-sha} --dest {R2's-sha},但我不知道我可以--keepbranches在最后添加。

如下Jonathan Blackburn所示:

 hg rebase -d default --keepbranches
于 2010-04-20T03:57:25.987 回答
44

假设你有一个现代 Hg 安装,你可以简单地添加:

[extensions]
rebase = 

到 ~/.hgrc。

然后您可以使用命令hg rebasehg pull --rebasehg help rebase

于 2010-04-20T04:02:34.727 回答
21

我不认为上面的答案实现了 OP 的目标,即维护他的任务分支,只是根据父分支的稍后点重新设置。

假设我从这个图开始(使用 graphlog 扩展生成。对 graphlog 的极客热爱)。

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

如果我在 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  

任务完成?我不这么认为。问题是,当 feature3 分支上的提交再次被 rebase 时,feature3 分支被删除了。我的提交已移至默认分支,这是我一开始就试图避免的。

在 Git 中,结果如下所示:

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

请注意,feature3 分支仍然存在,两个提交仍然在 feature3 分支上,默认情况下不可见。如果不保留任务分支,我看不出这在功能上与合并有何不同。

更新:我发现了--keepbrancheshg rebase 支持的标志,我很高兴地报告一切正常。使用hg rebase -d default --keepbranches,我完全复制了我渴望的 Git 行为。几个别名之后,我像没人的事一样重新定位。

于 2013-04-19T16:05:38.990 回答
3

由于有些人插话说他们认为保留所有内容的每次迭代都很好,我要指出,对于较大的开源项目,接受充满合并和开发迭代的更改会导致主线修订历史混乱,并使修订历史对于查看当前版本是如何到达那里的用处不大。

当提交的更改在被接受之前由没有编写它们的人审查时,这很有效,因此进入主线的更改通常都经过调试和工作。然后,当您回溯到一条线的原点时,您会看到所有随之而来的变化,而不是它所属的变化发展过程中的某个点。

x265 贡献者页面解释了如何重新提交您正在处理的一组更改,以使它们准备好提交到x265 项目。(包括使用 TortoiseHG 在单个文件中提交一些但不是全部更改,例如 git gui 的 stage/unstage diff hunk for commit)。

该过程是将 hg 更新到上游提示,然后在工作目录中未提交所有更改。搁置任何不属于您要提交的内容的部分,然后将其余部分分解为尽可能多的单独提交,并附上漂亮的提交消息。

我猜你会复制/粘贴,然后从你正在修改的补丁集的先前迭代中编辑提交消息。或者,也许您可​​以移植您的旧提交(git 语言中的cherry-pick),然后逐个修改它们,以获取旧的提交消息作为编辑的起点。

于 2014-12-15T03:48:53.437 回答