如何修改旧的 Git 提交? [复制]

Posted

技术标签:

【中文标题】如何修改旧的 Git 提交? [复制]【英文标题】:How to amend older Git commit? [duplicate] 【发布时间】:2012-02-08 03:29:20 【问题描述】:

我做了 3 次 git 提交,但没有被推送。 如何修改不是最新的旧的 (ddc6859af44) 和 (47175e84c)?

$git log
commit f4074f289b8a49250b15a4f25ca4b46017454781
Date:   Tue Jan 10 10:57:27 2012 -0800

commit ddc6859af448b8fd2e86dd0437c47b6014380a7f
Date:   Mon Jan 9 16:29:30 2012 -0800

commit 47175e84c2cb7e47520f7dde824718eae3624550
Date:   Mon Jan 9 13:13:22 2012 -0800

【问题讨论】:

请说明您是否想将这 2 个提交合并为 1 个提交,或者您是否想通过进一步的更改来修改每个提交。 我已经为此目的创建了一个 Bash 脚本:github.com/colinodell/git-amend-old 安装后,您可以像这样使用它:git amend-old abcd123,其中abcd123是您想要通过分阶段更改修改的旧提交。希望有人觉得它有用! 【参考方案1】:

您可以使用git rebase 重写提交历史。这可能会对您的更改造成潜在破坏,因此请谨慎使用。

首先将您的“修改”更改作为正常提交提交。然后从最旧提交的父级开始进行交互式变基

git rebase -i 47175e84c2cb7e47520f7dde824718eae3624550^

这将通过所有提交启动您的编辑器。重新排序它们,以便您的“修改”提交低于您要修改的提交。然后用 s 将行中的第一个单词替换为“修改”提交,这会将 (s quash) 与之前的提交结合起来。保存并退出编辑器并按照说明进行操作。

【讨论】:

他不想压缩或重新排序提交。 @AdamDymitruk:他在哪里说的?顺便说一句,您的回答还建议改写历史。 @AdamDymitruk:修改是提交和压缩最后两个提交的简写。两者都更改了提交 SHA1(“重写历史记录”)。如果我有错误的心理图片,请教育我。 我已对请求 OP 澄清的问题添加了评论。正如它现在所读的那样,我将其解释为他想要更改这 2 个提交而不是压缩或重新排序它们。 amend 添加到最后一次提交 - 无论您是否在变基中。 Squash 需要 2 个现有提交并将它们变成 1 个。我错过了什么?【参考方案2】:

您可以使用git rebase --interactive,在要修改的提交上使用edit 命令。

【讨论】:

【参考方案3】:
git rebase -i HEAD^^^

现在用edite 标记您要修改的那些(替换pick)。现在保存并退出。

现在进行更改,然后

git add .
git rebase --continue

如果您想添加额外的删除,请从 commit 命令中删除选项。如果要调整消息,请仅省略 --no-edit 选项。

【讨论】:

使用 git stashgit stash [-p|--patch](交互式)在 rebase 期间轻松地将更改应用到较旧的提交可能会很方便。 注意 - 你不必在 git add -A 之后 git commit,只需 git rebase --continue 会保留你的更改。 no matches found: HEAD^^^ @kleinfreund 两年后你可能已经解决了这个问题,但是对于其他任何人(比如我)来说,有这个问题:一些 shell(比如 zsh)将 ^ 解析为一个模式。在这种情况下,您可以改用~ @DarkFranX "HEAD^^^" 表示“头部前 3 次提交”【参考方案4】:

如果 OP 想要将指定的 2 个提交压缩为 1 个,这里是另一种无需变基的替代方法

git checkout HEAD^               # go to the first commit you want squashed
git reset --soft HEAD^           # go to the second one but keep the tree and index the same
git commit --amend -C HEAD@1   # use the message from first commit (omit this to change)
git checkout HEAD@3 -- .       # get the tree from the commit you did not want to touch
git add -A                       # add everything
git commit -C HEAD@3           # commit again using the message from that commit

@N) 语法很容易知道,因为它可以让您引用您的引用所在的历史记录。在这种情况下,它是 HEAD 代表您当前的提交。

【讨论】:

【参考方案5】:

我准备了我的提交,我想用一个旧的进行修改,并且惊讶地看到变基 - 我抱怨我有未提交的更改。但是我不想再次指定旧提交的编辑选项进行更改。所以解决方案非常简单明了:

    准备更新到旧提交,添加并提交 git rebase -i <commit you want to amend>^ - 请注意 ^,以便您在文本编辑器中看到上述提交

    你会得到这样的东西:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    pick e23d23a fix indentation of jgroups.xml
    

    现在将 e23d23a 与 8c83e24 结合起来,您可以更改线路顺序并像这样使用壁球:

    pick 8c83e24 use substitution instead of separate subsystems file to avoid jgroups.xml and jgroups-e2.xml going out of sync    
    squash e23d23a fix indentation of jgroups.xml
    pick 799ce28 generate ec2 configuration out of subsystems-ha.xml and subsystems-full-ha.xml to avoid discrepancies
    

    写入并退出文件,您将看到一个编辑器来合并提交消息。这样做并保存/退出文本文档

    您已完成,您的提交已修改

归功于:http://git-scm.com/book/en/Git-Tools-Rewriting-History 还有其他有用的演示 git 魔法。

【讨论】:

我没有意识到我可以重新排序变基文件中的行。很棒的提示! 如果有人不熟悉在终端编辑文件的vi命令,这个页面是一个很好的参考cs.colostate.edu/helpdocs/vi.html @DanBechard 重新排序行时要小心:如果您不小心剪切并忘记粘贴:该提交已消失!【参考方案6】:

我用过另一种方式好几次了。事实上,它是一本手册 git rebase -i,当您想要重新排列多个提交(包括压缩或拆分其中一些)时,它很有用。主要优点是您不必一次决定每个提交的命运。在此过程中,您还将拥有所有可用的 Git 功能,这与变基期间不同。例如,您可以随时显示原始历史和重写历史的日志,甚至可以进行另一个 rebase!

我将通过以下方式引用提交,因此它易于阅读:

C # good commit after a bad one
B # bad commit
A # good commit before a bad one

一开始你的历史是这样的:

x - A - B - C
|           |
|           master
|
origin/master

我们将以这种方式重新创建它:

x - A - B*- C'
|           |
|           master
|
origin/master

程序

git checkout B       # get working-tree to the state of commit B
git reset --soft A   # tell Git that we are working before commit B
git checkout -b rewrite-history   # switch to a new branch for alternative history

现在使用git addgit add -igit stash 等)改进您的旧提交。您甚至可以将旧的提交拆分为两个或更多。

git commit           # recreate commit B (result = B*)
git cherry-pick C    # copy C to our new branch (result = C')

中间结果:

x - A - B - C 
|    \      |
|     \     master
|      \
|       B*- C'
|           |
|           rewrite-history
|
origin/master

让我们结束吧:

git checkout master
git reset --hard rewrite-history  # make this branch master

或者只使用一个命令:

git branch -f master  # make this place the new tip of the master branch

就是这样,你现在可以push你的进度了。

最后的任务是删除临时分支:

git branch -d rewrite-history

【讨论】:

以上是关于如何修改旧的 Git 提交? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何从旧提交创建新的 Git 分支? [复制]

git修改提交信息

git 修改提交记录

如何在 Git 中标记较旧的提交?

是否可以修复 git 中的旧提交? [复制]

如何只提取Git某次提交修改过的文件