如果我推送修改后的提交,它将创建一个新的提交

时间:2016-04-01 08:43:53

标签: git push amend

我已经在远程分支上推送了一个提交,现在我想改变它的内容,所以我尝试了git修改。如果执行git status,则表示两个分支分别具有1个和1个不同的提交。现在,如果我使用相同的提交消息推送修改后的提交,那么会添加新提交还是会更改我推送的最后一次提交?

3 个答案:

答案 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)

TL;博士

推送修改后的提交意味着推送不同的提交。

提交ID的剖析

提交的唯一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个后面的消息。

要解决此问题,您需要创建一个新分支以保留修改,检查退出初始分支,重置回修改之前,从遥控器下拉变更。然后在你的单独分支中合并并推回。