Hg:如何像git的rebase那样做一个rebase

jps*_*ain 207 git mercurial dvcs rebase

在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


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

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

hg up -C F  
hg branch -f newfeature-123  
hg transplant -a -b newfeature-123 

并不是太糟糕,除了它作为一个未合并的头留下了预先重组的MNO并创建了3个新的提交M',N',O'代表它们从更新的主线分支出来.

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

master A---B---C---D---E---F
                \           \
newfeature-123   \           M'---N'---O'
                  \
newfeature-123     M---N---O

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

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

这确实产生了所需的图形:

master A---B---C---D---E---F
                            \
newfeature-123               M---N---O

但是这些命令(全部6个!)看起来要复杂得多

$ git rebase master

我想知道这是否是Hg中唯一的等价物,或者是否有其他方法可以像Git一样简单.

Ry4*_*ase 234

VonC有你想要的答案,Rebase扩展.然而,值得花一两秒时间考虑为什么默认情况下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
Run Code Online (Sandbox Code Playgroud)

这真的是必要的.我最终得到了一个newfeature-123克隆,当我对它很满意时,我可以很容易地回到主线.然而,最重要的是,我从未改变历史.有人可以查看我的cset并查看它们最初编码的内容以及我在整个工作中对主线的变化的反应.不是每个人都认为它有价值,但我坚信,源代码控制的工作不是向我们展示我们希望发生的事情,而是实际发生的事情 - 每一个deadend和每个重构都应该留下不可磨灭的痕迹,并且重新定位和其他历史编辑技术隐藏.

现在,在我把肥皂盒拿走的时候去挑选VonC的答案.:)

  • VonC,我同意,合并并不总是正确的选择,但我认为差异在于人们希望VCS历史能够告诉他们.我认为历史应该能够回答诸如"我最初尝试整合它的方式是什么,但是我觉得当时没用".科学家们将日志与笔记本保持在一起,AFAIC软件工程师应该保存他们输入的每个字节.重写历史,甚至cset父母,但肯定CollapseExtension,HistEdit等违反了这一点.这完全取决于个人选择. (18认同)
  • 注意:当然,Git并不*完全*允许您重写历史记录,只是为了轻松创建新的历史记录(http://utcc.utoronto.ca/~cks/space/blog/tech/GitNewHistory).通过添加RebaseExtension,Mercurial提供了用新的历史记录替换旧历史记录的同样方便的方法.为什么?因为合并并不总是正确的答案,特别是当您的变更集应该被视为F之上的*evolutions*而不是反之(P合并在O之上) (17认同)
  • +1为个人选择.因此,使用Git,我可以使用rebase进行琐碎的分歧,并将其合并为非平凡的.这允许我保留我觉得重要的合并历史记录,但在大多数情况下保持日志清洁和线性. (14认同)
  • 我还做了大量的交互式rebase,因为我倾向于首先进行大量的小提交,然后加入,标记和清理它们,然后将它们合并回主分支(或在其上面重新组合).我喜欢将编码和管理更改作为单独的步骤. (14认同)
  • "保存开发路径中的每个字节"理念并不适用于大型开源项目,其中贡献者提出了一组补丁,然后根据维护者的反馈对其进行返工.然后,最终主项目存储库只具有所有更改的正确版本,并且在单个提交中具有所有相关更改.git interactive rebase非常适合将工作更改清理为一系列不会使树被破坏的提交,并且提交消息反映了在完成整个工作之后您决定要说的内容. (5认同)

Von*_*onC 103

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

在这些情况下,"分离"本地更改,将存储库与主流同步,然后在新的远程更改之上附加私有更改可能很有用.此操作称为rebase.

来自:

替代文字

至:

替代文字


下面步骤评论:

如果您没有提取更改,并且您的仓库中有两个分支,则可以执行(使用keepbranches):

hg up newfeature-123 
hg rebase -d master --keepbranches
Run Code Online (Sandbox Code Playgroud)

(--keepbranches:继承原始分支名称.)

Mojca提到:

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

正如如下图所示乔纳森·布莱克:

 hg rebase -d default --keepbranches
Run Code Online (Sandbox Code Playgroud)

  • 如果您没有进行更改,并且您的仓库中有两个分支,则可以执行以下操作:`hg up newfeature-123`后跟`hg rebase -d master --keepbranches` (6认同)
  • 我相信重新设置没有什么错,这只是选择问题。问题在于,rebase被滥用了,我使用@ Ry4an来处理此事件,因此不会重写历史记录,因此您可以知道会发生什么情况以及何时发生。 (2认同)

sbl*_*lom 44

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

[extensions]
rebase = 
Run Code Online (Sandbox Code Playgroud)

到〜/ .hgrc.

然后你可以使用的命令hg rebase,hg pull --rebasehg help rebase.

  • 只是为了在命令方面添加这个,那么你需要执行的是:`hg rebase -so -df` (2认同)

Jon*_*urn 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   
Run Code Online (Sandbox Code Playgroud)

如果我在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  
Run Code Online (Sandbox Code Playgroud)

任务完成?我不这么认为.问题是当feature3分支上的提交再次重新绑定时,feature3分支被删除.我的提交已经转移到默认分支,这是我首先想要避免的.

在Git中,结果如下所示:

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo
Run Code Online (Sandbox Code Playgroud)

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

更新:我发现了--keepbrancheshg rebase支持的标志,我很高兴报告一切都是okey-dokey.使用hg rebase -d default --keepbranches,我完全复制了我渴望的Git行为.后来有几个别名,我像任何人的业务一样反对.

  • 刚刚在rebase上发现了--keepbranches标志.问题解决了.如果我的代码是默认的,那就是我. (7认同)