【问题标题】:Hg: How to do a rebase like git's rebaseHg:如何像 git 的 rebase 一样做 rebase
【发布时间】:2011-02-09 23:16:38
【问题描述】:

在 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. 我承认这一点:(将示例中的修订替换为我自己示例中的修订)

hg up -C F hg 分支 -f newfeature-123 hg 移植 -a -b newfeature-123

并不算太糟糕,只是它留下了 pre-rebase M-N-O 作为未合并的头部,并创建了 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。

【问题讨论】:

  • “这不好,因为它留下了应该丢弃的本地、不需要的提交。” -- 实际上,git 做同样的事情。它不会更改或删除原始分支中的提交,它只会创建在 master 之上应用相同更改集的新提交。您仍然可以使用git reflog 访问旧的,并且在它们被垃圾收集之前它们并没有完全消失。如果您想将它们保留在命名分支中,这样您就不必使用 reflog,只需在变基之前执行git branch feature-123_original
  • 随机问题:您是自己 ascii 绘制变更集/分支,还是有工具可以这样做?
  • 自己做的,TextWrangler 设置为“覆盖”。
  • 我自己最近同时使用 hg 和 git 我也注意到它们的行为不同。对于像我一样到达这里的人们,正在寻找问题:正如下面的其他答案所指出的,这些天使用--keepbranches。如果你使用 TortoiseHg,rebase 对话框中有一个开关。

标签: git mercurial dvcs rebase


【解决方案1】:

VonC 有 the answer you're looking for,即 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

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

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

【讨论】:

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

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

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

Getting from:

到:


作为commented belowsteprobe

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

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

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

Mojca 提及:

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

作为illustrated belowJonathan Blackburn

 hg rebase -d default --keepbranches

【讨论】:

  • 我查看了 Rebase 扩展,但我仍然不清楚。你能解释一下我上面描述的步骤吗?
  • 如果您没有拉入更改,并且您的仓库中有两个分支,您可以这样做:hg up newfeature-123 后跟 hg rebase -d master --keepbranches
  • 我相信 rebase 没什么问题,这只是一个选择问题。问题是 rebase 被滥用了,我和@Ry4an 一起讨论这个不要重写历史,这样你就可以知道发生了什么以及什么时候发生。
  • @steprobe:感谢您提供使用 --keepbranches 的提示。我喜欢使用hg rebase --source {L1's-sha} --dest {R2's-sha},但我不知道我可以在最后添加--keepbranches。这在其他排名较低的答案中有所提及,但最好也明确地将其写入此答案。
  • @Mojca 没问题。我已经相应地编辑了答案。
【解决方案3】:

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

[extensions]
rebase = 

到 ~/.hgrc。

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

【讨论】:

  • 只是添加到这个命令中然后你需要执行的是:hg rebase -s o -d f
【解决方案4】:

我不认为上面的答案实现了 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 分支上的提交再次重新基于时,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 分支上,默认情况下不可见。如果不保留任务分支,我看不出这在功能上与合并有何不同。

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

【讨论】:

  • 刚刚在 rebase 上发现了 --keepbranches 标志。问题解决了。如果这是我的代码,我会将其设为默认值,但这只是我自己。
  • 我认为如果您在上面的回复中添加这些信息会很有用 - 我花了一段时间才找到它。
【解决方案5】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 2016-05-21
    相关资源
    最近更新 更多