【问题标题】:How to amend older Git commit? [duplicate]如何修改旧的 Git 提交? [复制]
【发布时间】: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是您想要通过分阶段更改修改的旧提交。希望有人觉得它有用!

标签: git version-control git-rewrite-history


【解决方案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】:

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

      1. 准备更新到旧提交,添加并提交
      2. git rebase -i <commit you want to amend>^ - 请注意 ^,以便您在文本编辑器中看到上述提交
      3. 你会得到这样的东西:

        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
        
      4. 现在将 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
        
      5. 写入并退出文件,您将看到一个编辑器来合并提交消息。这样做并保存/退出文本文档

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

      归功于: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
      

      【讨论】:

        猜你喜欢
        • 2012-09-22
        • 2017-11-19
        • 1970-01-01
        • 1970-01-01
        • 2013-06-24
        • 2018-12-30
        • 1970-01-01
        • 2016-06-23
        • 2014-10-19
        相关资源
        最近更新 更多