git commit --amend 究竟是如何工作的?

29

1
发现了这篇很棒的文章:https://medium.com/@igor_marques/git-basics-adding-more-changes-to-your-last-commit-1629344cb9a8 - infiniteLearner
4个回答

51
假设您处于干净的工作状态,并且您的代码库如下所示:

Enter image description here

如果你接着运行

git commit --amend

编写提交信息,保存并退出编辑器后,会发生以下情况:

  1. 使用您的暂存区(如果您没有暂存任何新更改,则与提交 f42c5 相同)创建一个新的提交:31b8e。它的父级将与您要修改的提交的父级相同:f42c5
  2. master 分支引用被移动到指向该新提交(31b8e)。
  3. HEAD 引用跟随 master

Enter image description here

请注意,修改后的提交(f42c5)现在从您存储库中的任何引用都无法访问(因此在我的图表上呈“透明”样式)。它仍然存在于您存储库的对象数据库中,但当Git运行其定期清理或者您通过运行git gc(垃圾回收)显式触发时,它最终将被永久删除。

附录(基于Jason Baker的评论):请注意,只要修改后的提交f42c5仍然存在于您的存储库中,并且您有一种找到其提交ID的方法(例如,从master分支的reflog中找出它),您仍然可以检查它。运行

git checkout master # just to be sure that master is the current branch
git reset --hard f42c5

或者(假设您在此期间没有在master上进行任何新的提交,重置master或以其他方式移动了master分支引用)

git checkout master # just to be sure that master is the current branch
git reset --hard master@{1}

会让你陷入以下情况:

Enter image description here

然而,提交31b8e现在将无法到达。



你能通过checkout或者通过reflog回到f42c5吗?我承认这样做可能很愚蠢,但我很好奇是否可以访问旧的提交记录。 - Jason Baker
1
@JasonBaker 是的,只要修订(现在无法访问)提交尚未被垃圾回收,并且您有一种引用它的方式,您就可以随时查看它。 - jub0bs
1
嘿,现在命令不太对了,git reset 总是 重置当前分支(这意味着HEAD不能分离)。先放checkout master等命令。 - torek
@torek 糟糕...我最终会搞定的...对于我的时区来说,现在已经太晚了 :) - jub0bs
不过如果你已经在处理这个问题了,就不需要重置了。这只是为了确保我们知道“reset”正在重新设置什么。 - torek
显示剩余3条评论

11

假设你刚刚犯了“B”的错误

... --- A --- B
              ^
              |
            master
             HEAD

修改“B”将创建一个平行提交,该提交成为新的分支头。

        +---- B
        |
... --- A --- B'
              ^
              |
            master
             HEAD

B'是由B中的更改和您在执行git commit --amend时暂存的更改组合而成的提交。


2
为了进一步完善这个答案,B' 将包含来自 B 的更改组合以及您当前在存储库中等待的任何暂存更改。 - Jason Baker
"组合" 到底是什么意思?也许需要更新答案? - Peter Mortensen
B'是由从B中的更改与您在执行git commit --amend时暂存的更改组合而成的提交。对我来说非常重要。直到现在,我只使用git commit --amend来更改提交消息。我不知道我可以使用git commit --amend来更新提交中的更改。 - bit
1
@bit 当然。事实上,我经常使用-C HEAD(而不是-m'...')来避免改变信息。 - ikegami
1
@bit 当然。实际上,我经常使用-C HEAD(而不是-m'...')来避免改变信息。 - undefined

1
根据我的了解,amend 的工作方式如下:
对于 git commit --amend,要修正的更改必须位于暂存区(SA)中。
  1. 它执行 git reset --soft,将上次提交的更改(待修正的提交)恢复到暂存区,并将索引移动到前一个提交(待修正的提交之前的提交)。所有内容保持在使用 git commit 命令之前的状态。
  2. 它使用 git add 将所有文件添加到新的提交(即修正后的提交)。要添加的文件是在执行 git reset --soft 命令之前位于暂存区的文件,在重置之后这些文件仍然保存在工作目录(WD)中,因此需要将它们添加到暂存区以生成修正后的提交
  3. 它执行 Git 提交。这将生成一个新的提交,因此修正后的提交将具有新的标识符。因此,git commit --amend 不应与已推送的提交一起使用。
如果您使用--no-edit,则注释将在修改的提交中被重用,否则您必须引入一个新的注释(因为它是一个新的提交,每个提交都需要一个注释)。
有关暂存区和工作目录的更多信息,请参见 重置解密

-1
假设您创建了两个文件test1.txt和test2.txt,然后运行:
git add test1.txt && git commit -m “test1.txt and test2.txt “

后来你想起来忘记添加test2.txt了 所以你想要添加丢失的test2.txt文件并修改之前的提交 git add test2.txt

git commit --amend -m "test1.txt & test2.txt added"

git log [to see that the previous commit message updated and test2.txt file added]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接