繁体   English   中英

编辑git仓库的第一次提交未按预期工作

[英]Edit first commit of git repository not working as expected

我有一个非常简单的git存储库,它是为培训而创建的。 它有一个仅包含初始提交的master分支,以及几个从master植根的分支。 关键是我想编辑初始提交(由master指向)以添加带有一些指令的自述文件,但是这样做之后,似乎没有创建第一个提交,而是创建了一个新的提交,并且master分支更新以指向它。 我尝试了不同的策略来做到这一点:修改第一次提交并使用--root选项交互地进行基础调整,但是所有这些都会产生相同的结果。

这是我的git日志:

* e2c1de0 (origin/rerere-base, rerere-base) Add second line to 
rerere/file.txt to provoke a conflict
* 58af1bf Add file.txt for rerere example
...
| * 91d8f5b (origin/bisect-run, bisect-run) Add new test for minus
| * c7db602 Intentionally add a failing commit
...
| * 4ffaae9 Add calculator class with sum method
| * 188e648 Create package skeleton
|/
* 1d44a36 (HEAD -> master, origin/master, origin/HEAD) Initial commit

这是编辑第一次提交后的结果:

* 60f5e5c (HEAD -> master) Initial commit
* e2c1de0 (origin/rerere-base) Add second line to rerere/file.txt to provoke a conflict
* 58af1bf Add file.txt for rerere example
...
| * 91d8f5b (origin/bisect-run) Add new test for minus
| * c7db602 Intentionally add a failing commit
...
| * 4ffaae9 Add calculator class with sum method
| * 188e648 Create package skeleton
|/
* 1d44a36 (origin/master, origin/HEAD) Initial commit

请注意,新的提交已添加了消息Initial commit ,并且其父级是e2c1de0 (origin/rerere-base)而不是原始的初始提交。 真的很奇怪,不是吗?

有人可以向我解释发生了什么,理想情况下可以提供解决方案吗?

前面提到的原始存储库位于https://github.com/beni0888/gitlikeapro ,以防万一有人想要自己尝试。

提前致谢!

编辑:由于@torek的回答,我已经能够了解这里发生了什么。 该问题暗示两件事:

  • 我知道使用rebase修改或编辑以前的提交意味着重写历史记录并生成一个新的提交。 但是,我认为从属提交(例如,具有先祖的提交)已正确更新,恐怕不是这样。
  • 我使用带有--oneline选项的git log来检查历史记录,这使我产生了误解,因为我认为新生成的提交不是root提交,而是历史记录中的前一个提交,这是不正确的,如果您显示的历史记录不带--oneline选项,则可以对其进行检查。

看到下面的区别:

* commit 60f5e5c474719f2a6557859b04154c1b7a4d9e4b (HEAD -> master, origin/master, origin/HEAD)
  Author: ...
  ...
* commit e2c1de0a44be64e187a16a4e6bb380caef2343b7 (origin/rerere-base)
| Author: ...
| ...  
* commit 58af1bfce7a5a27143a3ca5dff464e004306c7f5
| Author: ...
| ...
...

这很正常。 任何更改提交的尝试实际上都会产生一个新的提交。

1更改提交实际上是不可能的,因为提交的哈希ID是提交内容的加密校验和。 如果您进行具有不同内容的新提交,则这是具有不同哈希ID的不同提交。

这就是git rebase工作方式:它需要整个现有提交链,并从中进行新的,改进的, 不同的提交。 然后,用于查找最后一个旧的迟钝提交的分支名称将被重写,以指向最后一个闪亮的新提交。 任何不知道旧提交的哈希ID,仅使用名称来访问提交的人,都会看到新提交:好像它们已更改。

但是,仍然具有原始提交的哈希ID的任何人都可以在旧ID下看到提交,因为它们仍在存储库中。

为了使每个人都可以使用新提交,在将所有提交复制到新提交之后,必须为所有您尝试更改但实际上已被复制的提交“后”(从后到)提交,重写所有名称。 这是因为每个后续提交都包含其父级的哈希ID,因此您需要将子级复制到具有新的父级且不同的父级的新提交中,然后复制该子级的子级以其父级重新编号,依此类推。

请注意, 不带 --oneline git log --graph将向您显示新提交是根提交。 使用--oneline很难说是这种情况,因为ASCII图形图在同一列中只有两个*字符:

* <hash> new root commit
* <hash> tip of other branch

如果有更多的文本行,您将看到以下两者之间的区别:

* <hash> tip of some branch
|        that uses more than one
|        line in the output
|
* <hash> another commit

和:

* <hash> new root commit
         with more than one line

* <hash> tip of some branch
...

其他图形查看器(gitk,git-gui等)绘制出更好的图形线条并使其更清晰,但是很少有像这样的多个根出现的。


1好吧,并不是完全不可能:如果您发现哈希冲突(例如,请参阅https://shattered.it/ ),则可以进行两个具有单个哈希ID的不同提交。 但是,由于Git的内部设置,如果您的新对象具有相同的哈希ID,则无法替换旧对象,因此即使在这种情况下也无法更改提交。 您可以做的是仔细构造两个单独的存储库,一个存储库的一个提交具有冲突的ID,另一个存储库的另一个提交具有相同的ID。

我想编辑初始提交(由主机指向)以添加一些说明的自述文件

将新文件添加为新提交。

如果您需要多个分支,请合并或选择。


修改公共承诺-别这么做。

Git doco指出:

--amend (...)如果您修改已发布的提交,则应该了解重写历史的含义。 (请参阅git-rebase中的“从UPSTREAM REBASE恢复”部分。)

从UPSTREAM REBASE状态恢复

对其他人基于其工作的分支重新建立基础(或进行任何其他形式的重写)是一个坏主意:该分支下游的任何人都必须手动修复其历史记录。

如有疑问,您将在此获得另一条教程信息

不要修改公共承诺

修改过的提交实际上是全新的提交,而先前的提交将不再位于您当前的分支上。 这具有与重置公共快照相同的结果。 避免修改其他开发人员基于其所做的提交。 对于开发人员来说,这是一个令人困惑的情况,并且要从中恢复很复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM