如何修改旧的Git提交?

时间:2012-01-11 18:52:57

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

我做了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

6 个答案:

答案 0 :(得分:168)

git rebase -i HEAD^^^

现在使用edite标记要修改的内容(替换pick)。现在保存并退出。

现在进行更改,然后

git add -A
git commit --amend --no-edit
git rebase --continue

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

答案 1 :(得分:94)

我准备好了我想用旧版本修改的提交,并且惊讶地看到rebase -i抱怨我有未提交的更改。但我不想再次指定旧提交的编辑选项进行更改。因此,解决方案非常简单明了:

  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. 您已完成,您的提交已修改
  7. 信用额度为:http://git-scm.com/book/en/Git-Tools-Rewriting-History 还有其他有用的演示git魔法。

答案 2 :(得分:12)

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

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

git rebase -i 47175e84c2cb7e47520f7dde824718eae3624550^

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

答案 3 :(得分:11)

我已经用过另一种方式了几次。实际上,它是一个手动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

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

答案 4 :(得分:9)

您可以在要修改的提交中使用edit命令来使用git rebase --interactive

答案 5 :(得分:2)

如果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表示您当前的提交。