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


461

在过去的一个小时中,我已经更改了几件事,并一步一步地提交了它们,但是我才意识到,我忘记添加一些提交的更改文件。

日志如下所示:

    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

有任何想法吗?


Answers:


693

使用git rebase。特别:

  1. 使用git stash存储您要添加的变化。
  2. 使用git rebase -i HEAD~10(或您想要查看的许多提交)。
  3. a0865...通过pick将行开头的单词更改为,将要提交的问题()标记为可编辑edit。不要删除其他行,因为那样会删除提交。[^ vimnote]
  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则必须Insert按键进行编辑,然后Esc键入:wq以保存文件,退出编辑器并应用更改。或者,您可以配置一个用户友好的git的承诺编辑git config --global core.editor "nano"


23
如果您已取消暂存要添加到编辑中的更改,该怎么办?如果我藏起来,我不会git add
山姆

15
Sam,您可以简单地取消存储更改,而在有问题的提交时,它将正常运行。
omn​​ikron 2013年

17
注意:当您用标记提交时edit,请勿删除文件中列出的其他提交。如果这样做,提交将被删除,您必须按照以下步骤将其取回。
David Tuite

2
关于@DavidTuite所说的话,我不确定在git上做东西时的习惯是创建一个“ branchname-ref”分支来保存时间轴的当前状态,以防万一我搞砸了。完成后,将其删除。
拉斐尔

1
在步骤6中,包括。命令中的(点)。正确的命令:git add .
汤姆(Tom)

323

只需稍作更改即可“修复”旧提交,而不更改旧提交的提交消息,其中OLDCOMMIT类似于091b73a

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

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


  • git rebase --interactive将调出一个文本编辑器(可以配置)以确认(或编辑)rebase指令序列。该文件中有有关更改基准指令的信息。只需保存并退出编辑器(:wq中的vim)即可继续进行基准调整。
  • --autosquash会自动--fixup=OLDCOMMIT以所需顺序放置所有提交。请注意,--autosquash仅在使用该--interactive选项时有效。
  • ^OLDCOMMIT^意味着它是一个参考之前提交OLDCOMMIT

上面的步骤对于验证和/或修改rebase指令序列非常有用,但是也可以通过以下方式跳过/自动执行交互式rebase文本编辑器:

参见git commitgit rebase。与往常一样,在重写git历史记录时,您应该只修正或发布尚未发布给其他任何人(包括随机的Internet用户和构建服务器)的提交。


18
比其他选项清晰得多,它像一种魅力
Chris Mitchelmore 2015年

5
@Jonah:未打开编辑器来编辑提交消息,而是确认(或编辑)变基步骤。这是无法避免的;--autosquash仅在使用该--interactive选项时有效
乔尔·普拉

5
使用此解决方案,我陷入了git显示VIM的困境。我的问题是,我不知道如何使用VIM。我该如何摆脱困境,如何控制这件事,这是如此令人困惑。
霓虹灯Warge '16

2
@NeonWarge:可以使用例如来配置选择的编辑器git config --global core.editor "pico"。还有其他几种方法可以配置git和/或更改系统的默认编辑器等。
乔尔·普拉

2
一线好别名在这里
idanp '18

61

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

暂存文件:

git add $files

创建一个新的提交,并重新使用“断开”提交的提交消息

git commit -c master~4

前置fixup!主题行(或者squash!,如果你想编辑提交(消息)):

fixup! Factored out some common XPath Operations

用于git rebase -i --autosquash修正您的提交


2
+1。尼斯使用新修正指令(1.7+):stackoverflow.com/questions/2302736/trimming-git-checkins/...
VonC

@knittl我正在尝试将您的方法添加到我的旧提交中的另一个文件(未推送),但是在重新定基时得到You asked me to rebase without telling me which branch you want to rebase against, and 'branch.master.merge',如果我随后使用,git rebase -i --autosquash我会得到一个noop主题行,将提交重新定到其自身上。知道我做错了什么吗?
oschrenk 2012年

7
@oschrenk:您需要提供要作为基准的提交,例如git rebase -i --autosquash HEAD~10
knittl 2012年

1
好的答案,但是我还需要添加一个提交作为基础。如果您可以更新它会很棒。
Paul Odeon

@PaulOdeon:我不明白你的问题。您想做什么,哪里有问题?
knittl

8

您可以尝试使用rebase --interactive会话来修改您的旧提交(前提是您尚未将这些提交送到另一个存储库)。

有时,东西固定在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”),因此请勿删除或编辑名称。

通过将命令“ pick”替换为命令“ edit”,您可以告诉git rebase在应用该提交后停止,以便您可以编辑文件和/或提交消息,修改提交,并继续进行基础调整

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.