209

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

6 回答 6

258
git rebase -i HEAD^^^

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

现在进行更改,然后

git add .
git rebase --continue

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

于 2012-01-11T19:06:23.007 回答
160

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

  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 魔法。

于 2013-08-09T15:42:35.150 回答
16

我用过另一种方式几次。事实上,它是一本手册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 add现在使用(git add -i等)改进您的旧提交git 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
于 2013-08-19T07:24:25.777 回答
16

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

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

git rebase -i 47175e84c2cb7e47520f7dde824718eae3624550^

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

于 2012-01-11T18:55:22.767 回答
11

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

于 2012-01-11T19:01:30.420 回答
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 代表您当前的提交。

于 2012-01-11T20:52:29.577 回答