为什么'git rebase'保留了重新分支的历史?

sim*_*ich 0 git git-rebase

据我所知,从http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html,重新分支的分支被"移动"到另一个分支.

但是,我在测试中看到的结果表明,来自重新分支的分支的提交仍然在历史中,因此它们实际上是重复的.

在变基之前:

变基后:

也许我遗漏了一些东西或完全不了解rebase的目的或两者兼而有之.

如果我看到的是预期的行为,那为什么会这样呢?

Jef*_*ica 5

简而言之,rebase是一种将提交从树的一部分应用到不同起点的方法.它可以复制这些更改,但不会移动它们.

请记住,git提交是不可变的 - 一旦有东西有哈希,它就永远不会改变.这意味着当你在另一个变化之上重新定义一些变化时,散列必然是不同的,所以git将保持旧的和新的变化.

但是,如果没有分支名称指向旧提交(在您的示例中为"add file2"),那么几周后git的自动垃圾收集器将从您的存储库中删除旧提交.(为什么两个星期?这样,如果你改变主意,就可以从中检索旧的提交git reflog.)一般来说,这是一件好事 - 它会使意外丢失数据变得更加困难 - 但如果文件非常庞大您可以使用git prunegit gc删除冗余数据的组合.


me_*_*and 5

这里有两个不同的现象.

  1. 您从gitk发布的屏幕截图仍显示旧提交.这就是gitk的工作方式; 如果你通过点击Ctrl+ F5而不是仅仅F5(你的鼠标用户的文件>重新加载而不是文件>更新)重新加载,你会看到旧提交消失,因为它不再相关.

  2. Git中有很多操作可以创建提交.甚至更多的是在文件存储中创建文件或树对象.许多这些对象不再使用的事实是无关紧要的.

    这有很多优点.在您的示例中,这意味着如果您认为您的rebase是一个坏主意,您的旧提交仍然存在并且可以恢复.它甚至有一个方便的语法:topic@{1}指的是topic在它最后一次移动之前指向的提交; 在这里,这将是在rebase之前.

    Git对象模型对这类事情很聪明.有一个额外的承诺像这样躺在身边占用非常小的额外空间.对于像你所描述的那样的rebase,我希望坚持旧的分支最多花费几百个字节.

    当然,随着时间的推移,这确实会增加.因此git gc(每隔一段时间由某些命令自动运行)运行git prune.并且git prune会查找旧的且不再相关的提交和对象,并为您清除它们.

这并不意味着你的rebase没有起作用,只是因为rebase"移动"提交的想法是简化.rebase实际上做的是将每个提交及其父级之间的差异应用于新分支,并为旧分支上的每个提交创建一个具有这些差异的新提交.然后它会更新分支,这样,如果查看分支历史记录,就好像这些提交已被移动一样.