Git 如何更改过去的提交以包含丢失的文件?

Git 如何更改过去的提交以包含丢失的文件?,git,git-commit,Git,Git Commit,我已提交更改,但忘记将文件添加到更改集中。在其他提交之后,我意识到文件现在从头^4提交中丢失了 如何重写以前的提交以包含丢失的文件?为要修改的提交使用并设置编辑选项 请记住,不应以这种方式修改推送到远程存储库的提交。在这种情况下,最好添加一个缺少文件的新提交 为了更清楚地说明这一点,首先使用git stash隐藏任何当前更改。然后,git-rebase——交互式头~4。您可以在文本编辑器中获得以下内容(请注意,您将获得5次提交,按降序排列): 将更改条目的前缀从pick修改为edit。这将是操

我已提交更改,但忘记将文件添加到更改集中。在其他提交之后,我意识到文件现在从
头^4
提交中丢失了

如何重写以前的提交以包含丢失的文件?

为要修改的提交使用并设置
编辑
选项

请记住,不应以这种方式修改推送到远程存储库的提交。在这种情况下,最好添加一个缺少文件的新提交


为了更清楚地说明这一点,首先使用
git stash
隐藏任何当前更改。然后,
git-rebase——交互式头~4
。您可以在文本编辑器中获得以下内容(请注意,您将获得5次提交,按降序排列):

将更改条目的前缀从
pick
修改为
edit
。这将是操作的
编辑321e122…

git-rebase
按顺序遍历条目。因为我们只更改了一个条目,所以您只能更改一个条目。现在,使用
git add
添加您的文件,并使用
git commit--amend
修改这些添加的文件的当前提交


最后,
git-rebase--continue
移动到下一个文件。由于只有一个提交,因此重基已完成

如果您尚未推送这4个提交,则可以按如下方式执行:

为所有这些提交创建修补程序文件:

git format-patch -4
倒带4次:

git reset --hard HEAD~4
添加缺少的文件:

git add missing-file
提交它--修改

git commit --amend
将所有保存的修补程序应用回:

git am *.patch


如果您已按下,则不应使用此方法。相反,只要承认你的错误,在头上再做一次承诺就可以解决这个问题。

我意识到人们可以通过谷歌搜索到一个更简单的答案:如果这只是最后一次承诺呢? (OP的问题是修复历史上的第四次提交)

如果您提交并意识到忘记立即添加某些文件,只需执行以下操作:

# edited file-that-i-remember.txt
git add file-that-i-remember.txt
git commit

# realize you forgot a file
git add file-that-i-forgot.txt
git commit --amend --no-edit
其中
--没有编辑将保留相同的提交消息


轻松点

尽管接受的答案是正确的,但它缺少关于如何在重新基址过程中执行编辑提交的详细说明

  • 首先,启动一个重设基础的过程:

    git rebase --interactive HEAD~4
    
  • 将显示提交列表,通过将单词
    pick
    更改为
    edit
    选择要编辑的提交并保存文件

  • 对代码进行必要的修改(请记住为新文件调用
    git add

  • 完成所有修改后,发出
    git commit--amend
    -这将修改标记为
    edit

  • 调用
    git-rebase——继续
    ,这将完成该过程(如果有更多的提交标记为
    edit
    ,则需要重复上述步骤)

重要注意事项:

  • 不要删除标记为不想编辑的
    拾取
    行-保持原样。删除这些行将导致删除相关提交

  • 如果您的工作目录不干净,GIT会强制您在重定基址之前
    隐藏
    ;但是,您可以在重新基础期间
    git stash pop/git stash apply
    ,以便将这些更改(即在开始重新基础过程之前隐藏的更改)修改为标记为
    edit

  • 如果出现问题,并且您希望在重新基础过程完成之前还原所做的更改(即,您希望还原到启动重新基础之前的点),请使用
    git-rebase--abort
    -另请阅读:

  • 正如公认的答案所说:

    请记住,不应以这种方式修改推送到远程存储库的提交。在这种情况下,最好添加一个缺少文件的新提交

    答案是(题为“重新定价的风险”的段落):

    不要对存储库外部存在的提交重新设置基础

    如果你遵循这个指导方针,你会没事的。如果你不这样做,人们会恨你,你会被朋友和家人嘲笑

    当您重新设置内容的基础时,您放弃了现有的提交,并创建了相似但不同的新提交。如果您将提交推到某个位置,而其他人将其向下拉并基于它们进行工作,然后您使用git rebase重写这些提交并再次将其向上推,那么您的合作者将不得不重新合并他们的工作,当您尝试将他们的工作拉回到您的工作中时,事情将变得一团糟

    [……]


    • 这里有一种非交互式的
      重设基础的方法

      这需要一个额外的提交(因此不会像OP所要求的那样“重写以前的提交”),但我发现它更容易记住

      初始状态:

      * e834111 (HEAD -> master) do something that depends on file x
      * 6dde62a do stuff, forget to add file x
      ...
      
      步骤1-在提交时签出应包含该文件的新临时分支(
      git checkout-b temp 6dde
      ):

      步骤2-
      添加
      缺少的文件并提交

      * 50d1412 (HEAD -> temp) add file x
      | * e834111 (master) do something that depends on file x
      |/  
      * 6dde62a do stuff, forget to add file x
      ...
      
      第3步-签出原始分支并将其重新设置为
      temp

      * dd6f2dd (HEAD -> master) do something that depends on file x
      * 50d1412 (temp) add file x
      * 6dde62a do stuff, forget to add file x
      ...
      
      步骤4-删除临时分支(
      git分支-d temp


      注意:这也可以在不创建临时分支的情况下完成,例如使用
      git checkout 6dde
      ,然后是
      commit
      rebase
      到分离的磁头上。

      您是否将这4个提交推到了?@mvp nope,它们仅在我的本地git存储库中。如果您想一步一步地执行此操作,那么在修改后选择提交比将其导出为补丁更容易。这是一个品味问题。我更喜欢
      git格式的补丁
      /
      gitam
      。最重要的是,如果你把事情搞砸了,它会给你更多的信心——在物理文件中保存为补丁的提交是你最好的安全网。真正的信心在于,在git存储库上操作时,你永远不会删除任何东西。旧提交可用
      * 50d1412 (HEAD -> temp) add file x
      | * e834111 (master) do something that depends on file x
      |/  
      * 6dde62a do stuff, forget to add file x
      ...
      
      * dd6f2dd (HEAD -> master) do something that depends on file x
      * 50d1412 (temp) add file x
      * 6dde62a do stuff, forget to add file x
      ...