如何在Git中添加已更改的文件到旧的(不是最后的)提交

在过去的一个小时里,我已经改变了一些东西,并逐步提交了它们,但我刚刚意识到,我忘记在一些提交前添加一个更改过的文件。

日志看起来是这样的:

GIT TidyUpRequests u:1 d:0> git log
commit fc6734b6351f6c36a587dba6dbd9d5efa30c09ce
Author: David Klein <>
Date:   Tue Apr 27 09:43:55 2010 +0200


The Main program now tests both Webservices at once


commit 8a2c6014c2b035e37aebd310a6393a1ecb39f463
Author: David Klein <>
Date:   Tue Apr 27 09:43:27 2010 +0200


ISBNDBQueryHandler now uses the XPath functions from XPath.fs too


commit 06a504e277fd98d97eed4dad22dfa5933d81451f
Author: David Klein <>
Date:   Tue Apr 27 09:30:34 2010 +0200


AmazonQueryHandler now uses the XPath Helper functions defined in XPath.fs


commit a0865e28be35a3011d0b6091819ec32922dd2dd8 <--- changed file should go here
Author: David Klein <>
Date:   Tue Apr 27 09:29:53 2010 +0200


Factored out some common XPath Operations

什么好主意吗?

162598 次浏览

您可以尝试使用rebase --interactive会话来修改旧的提交(假设你还没有推将这些提交到另一个repo)。

有时东西固定在b.2。不能修改为它修复的不太完美的提交,因为这个提交被深深地埋在补丁系列中.
这正是交互式rebase的目的:在大量的“a”和“b”之后使用它,通过重新安排和编辑提交,并将多个提交压缩成一个

从你想保留的最后一个提交开始:

git rebase -i <after-this-commit>
编辑器将被启动,其中包含当前分支中的所有提交(忽略合并提交),这些提交位于给定的提交之后 您可以根据自己的意愿对列表中的提交进行重新排序,也可以删除它们。列表大致如下:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

这一行描述纯粹是为了让你高兴;Git rebase不会查看它们,而是查看提交名称(本例中为“deadbee”和“fa1afe1”),因此不要删除或编辑这些名称。

# EYZ0。

使用# EYZ1。具体地说:

  1. 使用git stash存储您想要添加的更改。
  2. 使用git rebase -i HEAD~10(或者您希望看到的提交数)。
  3. 通过将行开头的单词pick更改为edit来标记要编辑的提交(a0865...)。不要删除其他行,因为那样会删除提交。
  4. 保存rebase文件,git将返回shell并等待您修复提交。
  5. 使用git stash pop弹出隐藏
  6. git add <file>添加文件。
  7. 使用git commit --amend --no-edit修改提交。
  8. 执行git rebase --continue,它将根据新的提交重写其余的提交。
  9. 如果您标记了多个提交进行编辑,请从步骤2开始重复。

[^vimnote]:如果你使用vim,那么你必须点击插入键进行编辑,然后是Esc,然后输入:wq保存文件,退出编辑器,并应用更改。或者,你可以用配置一个用户友好的git提交编辑器git config --global core.editor "nano"

在git 1.7中,有一个非常简单的方法使用git rebase:

整理你的文件:

git add $files

创建一个新的提交并重新使用“坏了”提交的提交消息

git commit -c master~4

在主题行中添加fixup!(如果你想编辑commit (message),可以添加squash!):

fixup! Factored out some common XPath Operations

使用git rebase -i --autosquash来修复你的提交

“;fix"旧的提交有一个小的改变,没有改变旧提交的提交消息,其中OLDCOMMIT类似于091b73a:

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

您还可以使用git commit --squash=OLDCOMMIT在重基期间编辑旧的提交消息。

请参阅git提交git变基的文档。和往常一样,当重写git历史时,你应该只修复或压缩你还没有发布给任何人的提交(包括随机的互联网用户和构建服务器)。


详细解释


可选的自动化

上面的步骤对于验证和/或修改重构指令序列是很好的,但它也可以跳过/自动化交互式rebase文本编辑器:

下面是一个实现@Greg答案的函数:

function gitamendoldcommit() {
printf "\n\nPress any key if you have no changes other than those you want to add to $1."
printf "(You can commit your unwanted changes and undo later.):\n\n"
read foo
printf "\n\nChange 'pick' to 'edit' in front of $1 (top one), save, close the editor & press any key..."
printf "Resolve any possible conflicts, if any. then: git add .; git rebase --continue\n\n"
git rebase -i $1^


git stash pop
git add .
git commit --amend --no-edit
git rebase --continue
}

用法:(当只在分段中进行预期的更改时)gitamendoldcommit $OLDCOMMIT

另外,如果你使用git rebase -i并且想要去当前分支的第一次提交,你可以使用git rebase -i --root。现在您可以轻松地修改第一次提交。