如何编辑之前的git提交?

21

我刚意识到我在五次提交前应该添加到提交中的一个文件被遗漏了。在提交信息中,我说这个文件已经包含了,而且我不想再创建一个新提交,写上“糟糕,忘记在#XXXXX提交中添加这个文件”。

怎样才能修改以前的提交并添加这个文件是最好的方式呢?

3个回答

41

提交您的修复,然后使用git rebase --interactive重新排序提交并将两个提交压缩在一起。有关详细信息,请参见git书籍

请注意,如果这些提交已经被推送到某个地方,那么这样做是不好的,因为这将更改存储库历史记录。

一个示例会话可能如下所示:

% git init
Initialized empty Git repository in /home/user/repo/.git/
% echo "A line" > a.txt
% echo "A line" > b.txt
% git add a.txt b.txt
% git commit -m "Initial commit"
[master (root-commit) c6329d0] Initial commit
 2 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 b.txt

您的未完成提交:

% echo "Another line" >> a.txt
% git add a.txt
% git commit -m "Important changes"
[master 0d28cfa] Important changes
 1 files changed, 1 insertions(+), 0 deletions(-)

另一个提交:

% echo "Yet another line" >> b.txt
% git add b.txt
% git commit -m "Other changes"
[master 96a092d] Other changes
 1 files changed, 1 insertions(+), 0 deletions(-)

请注意,您忘记了某些内容:

% echo "Important line forgotten previously" >> a.txt
% git add a.txt
% git commit -m "Oops"
[master 9dce889] Oops
 1 files changed, 1 insertions(+), 0 deletions(-)

使用git rebase -i修复历史记录:

% git rebase -i HEAD~3
你将会被放入你选择的编辑器中,其中的内容类似于以下内容:
pick 0d28cfa Important changes
pick 96a092d Other changes
pick 9dce889 Oops

将"oops"提交移动到上一行,并将pick更改为squash(或只用s)以与之前的提交合并:

pick 0d28cfa Important changes
s 9dce889 Oops
pick 96a092d Other changes

然后保存文件并退出编辑。这将弹出另一个编辑器,在那里您可以编辑合并提交的提交消息。它将如下所示:

# This is a combination of 2 commits.
# The first commit's message is:

Important changes

# This is the 2nd commit message:

Oops

按你认为合适的方式进行更改,然后保存并退出。

最后,检查新提交是否确实是两个提交的组合:

% git log -p HEAD~2..HEAD~1
commit 7a4c496956eb269c551bbf027db8b0f2320b65e4
Author: User Name <user@host.tld>
Date:   Fri Feb 3 22:57:31 2012 +0100

    Important changes

diff --git a/a.txt b/a.txt
index 8d7158c..54df739 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,3 @@
 A line
+Another line
+Important line forgotten previously

我希望能够得到更详细的解释,甚至是一步一步的指导,但我想这已经是一个起点了。 - Hubro
2
我已经添加了一个例子,希望能帮到你! - Mika Fischer

15
你可以使用git commit --fixup <hash>命令创建一个特别标记的提交,该提交旨在与先前哈希为<hash>的提交合并。这非常适用于添加遗漏的文件或修正拼写错误等问题。
一旦你有了fixup提交,你需要使用git rebase --interactive --autosquash <starting-point>将fixup提交实际合并到<hash>提交中。rebase的<starting-point>应该是历史记录中<hash>提交之前的某个点(你可以简单地使用<hash>^)。
通常情况下需要注意的是,如果你已经将你的分支发布到其他用户拉取的地方,如果你推送具有重写历史记录的分支,它通常会导致很多混乱和合并问题。在这些情况下,更简单的方法是将更正作为新的提交推送。
注意:git config --global rebase.autosquash true将默认启用自动压缩,这意味着你不再需要将--autosquash选项传递给交互式rebase命令。这是一个很好的默认设置。
关于自动压缩的详细步骤可以在这里找到:https://thoughtbot.com/blog/autosquashing-git-commits

2
为了将其压缩成一个提交,需要执行 git squash
// X is the number of commits you wish to edit
git rebase -i HEAD~X

一旦你压缩了提交记录 - 选择 e 或 'r' 进行编辑。
在最新的提交记录中选择 "pick" 以保留它。

enter image description here


另一个选项是使用filter-branch。
以下是获取参数的方法,您可以使用新值更新它们并重新提交,而不是旧值。
在此示例中,我更改了电子邮件,但适用于消息。
git filter-branch --commit-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
    then
            GIT_COMMITTER_NAME="<New Name>";
            GIT_AUTHOR_NAME="<New Name>";
            GIT_COMMITTER_EMAIL="<New Email>";
            GIT_AUTHOR_EMAIL="<New Email>";
            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi' HEAD `

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