我已经在远程分支上推送了一个提交,现在我想改变它的内容,所以我尝试了git修改。如果执行git status,则表示两个分支分别具有1个和1个不同的提交。现在,如果我使用相同的提交消息推送修改后的提交,那么会添加新提交还是会更改我推送的最后一次提交?
答案 0 :(得分:12)
git commit --amend
,就像git rebase
一样,将创建一个新的提交对象。该对象基于先前存在的提交,但它仍然是新提交并完全替换旧提交。
观察历史,这可能是这样的:
master
↓
* --- * --- * --- A
考虑A
是原始提交。如果我们现在修改此提交,那么我们得到以下结果:
* --- * --- * --- A
\
--- A'
↑
master
所以我们得到一个不同的提交对象A'
,使用不同的哈希,并且我们所在的分支(这里:master)被更新为指向这个。
现在,如果我们向该视图添加一个远程存储库,并且我们先前将A
推送到远程,那么它看起来像这样:
origin/master
↓
* --- * --- * --- A
\
--- A'
↑
master
所以远程仍指向原始提交A
,但我们的本地分支指向修改后的A'
。这是一个问题,因为我们无法推送A'
并使origin/master
指向A'
,因为这会从历史记录中删除已经推送的提交A
。
我们可以使用git push --force
执行强制推送,以强制Git更新远程分支,并确实从历史记录中删除A
。重要的是要注意,这将打破已经从遥控器获取A
的每个人的历史记录。如果其他开发人员有A
,现在远程点位于A'
,那么他们就会发生冲突,他们必须手动修复。这通常是一件痛苦的事情,因此您应该始终遵循以下规则:
不要改变(或修改)先前发布的提交。
更好的选择是添加一个新的提交B
,只需对A
执行修复:
origin/master
↓
* --- * --- * --- A --- B
↑
master
这样,已发布的历史记录仍然与新历史记录兼容,因此我们可以将B
推送到远程而不会发生冲突,每个人都很高兴。
答案 1 :(得分:2)
推送修改后的提交意味着推送不同的提交。
提交的唯一ID由其元数据的SHA-1哈希组成。哪个元数据?找出答案的方法之一是使用cat-file
plumbing command:
git cat-file -p HEAD
运行此命令后,您将看到包含以下字段的列表:
如果这些字段中的任何更改,则其SHA-1哈希也将更改为授予提交整个新ID 。
这就是为什么如果你修改一个提交 - 例如通过改变它的消息 - 它会有一个不同的ID 而不是它先前。您实际上是rewriting history。
请注意,提交的父的ID也包含在元数据中。这意味着一旦提交更改ID,其所有后代也将更改ID ,就像多米诺骨牌效应一样。
答案 2 :(得分:1)
一旦你推到遥控器,就不应该在本地修改任何现有的提交。
您实际上在本地创建了一个新提交(有一个新的提交ID)并替换旧的提交但旧的仍然存在于远程。这会导致您看到1个前面和1个后面的消息。
要解决此问题,您需要创建一个新分支以保留修改,检查退出初始分支,重置回修改之前,从遥控器下拉变更。然后在你的单独分支中合并并推回。