在不影响标签的情况下,使用git修改master历史记录的最佳方法是什么?

时间:2014-04-25 17:53:07

标签: git git-merge git-interactive-rebase

我正在为一本书写一个示例应用程序。

标记每个重要的提交(例如Ch01_Ex04,Ch03_Ex01),以便读者可以直接进入他们感兴趣的应用程序的状态。

每隔一段时间我就会改变自己的想法,比如我在exxample中所做的事情。我想回到过去并改变,例如,一个班级名称。我希望从给定的提交中应用该更改,而不需要重置所有标记。

说我有:

 Tag1    Tag2    Tag3
  |       |       |
- A - B - C - D - E
                  |
                 HEAD

现在我想在B和C之间进行更改,所以我从B分支并进行更改,我有:

 Tag1    Tag2    Tag3
  |       |       |
- A - B - C - D - E
       \          |
        F        HEAD

我想要的是:

 Tag1        Tag2    Tag3
  |           |       |
- A - B - F - C - D - E
                      |
                     HEAD

我无法理解如何做到这一点。有办法吗?

2 个答案:

答案 0 :(得分:3)

  

我想回到过去,然后改变一个班级名称。我希望从给定的提交中应用该更改,而不需要重置所有标记。

 Tag1    Tag2    Tag3
  |       |       |
- A - B - C - D - E
                  |
                 HEAD
  

我想要的是:

 Tag1        Tag2    Tag3
  |           |       |
- A - B - F - C - D - E
                      |
                     HEAD

Git最强有力的保证是没人能做到

根本不可能(“因为数学”,特别是cryptographic hash functions背后的数学)将提交插入或对历史进行任何其他更改,而没有每个人都能立即检测到修改后的历史记录。

最接近的是

 Tag1        Tag2    Tag3
  |           |       |
- A - B - F - C*- D*- E*
                      |
                     HEAD

其中C*D*E*是新提交,其几乎完全像 CD,{ {1}} - 相同的提交消息,作者,日期,什么不是,除了他们的哈希码。这意味着标签必须重置。 git不会轻易地以这种规模重写。

The answer @Joe linked将向您展示如何在filter-branch完成重写历史记录后移动任何孤立标记,假设您选择了该路径。

但我建议你考虑一个不同的解决方案。

据我了解,您希望人们能够找到当前版本的例如“Ch01_Ex04”很容易,但随着写作的进行,这些都会改变。非常合理的东西。事实上,标签不是正确的解决方案。它们用于识别特定的,固定的,历史的内容分发。

通过将状态直接放在提交消息本身而不是通过其标记名称引用提交,而不是通过该内容识别它,可以最好地实现您想要的,识别当前提交的特定角色的内容提交。 :例如E ':/^===Ch01_Ex04==='将显示当前分支的最新提交,其消息开始为git show

答案 1 :(得分:0)

要修改历史记录中更远的提交,您必须转到更复杂的工具。 Git没有修改历史记录工具,但您可以使用rebase工具将一系列提交重新绑定到它们最初基于的HEAD上,而不是将它们移动到另一个。使用交互式rebase工具,您可以在每次提交后停止修改并更改消息,添加文件或执行任何操作。您可以通过向-i添加git rebase选项以交互方式运行rebase。您必须通过告知提交到rebase的命令来指示您想要重写提交的距离。

例如,如果要更改最后三个提交消息或该组中的任何提交消息,则作为参数提供给git rebase -i您要编辑的最后一个提交的父级,是HEAD~2^HEAD~3。记住~3可能更容易,因为您正在尝试编辑最后三次提交;但请记住,您实际上是指定了四个提交,即您要编辑的最后一个提交的父级:

$ git rebase -i HEAD~3

来源git documentation for rewriting history