我正在为一本书写一个示例应用程序。
标记每个重要的提交(例如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
我无法理解如何做到这一点。有办法吗?
答案 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*
是新提交,其几乎完全像 C
,D
,{ {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