从Git提交中删除文件

Lol*_*lly 1484 git git-commit

我正在使用Git,我已经提交了几个文件

git commit -a
Run Code Online (Sandbox Code Playgroud)

后来,我发现错误地将一个文件添加到了提交中.

如何从上次提交中删除文件?

juz*_*lin 2841

我认为这里的其他答案是错误的,因为这是一个将错误提交的文件从前一次提交移回到暂存区域的问题,而不取消对它们所做的更改.这可以像Paritosh Singh建议的那样完成:

git reset --soft HEAD^ 
Run Code Online (Sandbox Code Playgroud)

要么

git reset --soft HEAD~1
Run Code Online (Sandbox Code Playgroud)

然后重置不需要的文件,以便将它们从提交中删除:

git reset HEAD path/to/unwanted_file
Run Code Online (Sandbox Code Playgroud)

现在再次提交,您甚至可以重用相同的提交消息:

git commit -c ORIG_HEAD  
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你.值得补充的是,如果你已经推动了你之前的(错误的)提交,现在尝试`git push`你的修复你的回购,它会抱怨`更新被拒绝,因为你当前分支的提示落后于其远程对手.`.如果你确定要推它们(例如它是你的叉子)那么你可以使用`-f`选项强制推送,例如`git push origin master -f`.(不要对其他人提取的上游回购执行此操作) (79认同)
  • `git reset --soft HEAD ^`是我最常用的撤消操作 (52认同)
  • 我非常了解`git reset`但想要一种方法来影响现有的"就地"提交.我刚学会了`git commit -C`.所以对我来说,我想要的是你的确切配方还有一步,"新提交"又拼写为`git commit -C [原始HEAD提交的哈希从第一步开始]`. (14认同)
  • @PabloFernandez在所有答案的顶部是三个选项卡,允许您控制答案的顺序:**活跃**,**最旧**和**投票**.我的猜测是你的**最老**.切换到**票**即使接受的答案仍然在顶部,这个答案将是第二个. (4认同)
  • @PabloFernandez,首先,接受的答案可能是OP正在寻找的东西(另外,它是几个月前发布的).其次,无论票数多少,接受的答案总是排在最前面. (2认同)
  • 记得做一个实际的提交,而不是修改.如果这样做,它将修改先前的提交. - 哎呀 (2认同)

Cha*_*esB 296

注意!如果您只想从之前的提交中删除文件,并将其保存在磁盘上,请阅读上面的juzzlin的答案.

如果这是您的上次提交,并且您希望从本地和远程存储库中完全删除该文件,则可以:

  1. 删除文件 git rm <file>
  2. 提交修改标志: git commit --amend

修正标志告诉git再次提交,但是"合并"(不是在合并两个分支的意义上)这个提交与最后一次提交.

正如评论中所述,git rm在这里使用就像使用rm命令本身一样!

  • 你也可以使用`git rm --cached`将文件保存在磁盘上 (113认同)
  • 向浏览此答案的人发出警告:确保要删除文件(如已经消失!),而不仅仅是从提交列表中删除它. (13认同)
  • 添加其他人的说法(并且更容易记住不要这样做,除非你真的想要):**`git`命令中的`rm` _is_做什么`rm`本身呢!** (8认同)
  • 请注意,文件仍然可以恢复,如果您改变主意,`git commit --amend` 之前的提交仍然存在,例如可以通过 `git reflog` 找到。所以它并不像其他评论所暗示的那么糟糕。 (3认同)
  • 推送时,如果您使用“--amend”,则需要强制推送:“git push -f”。 (2认同)

Bri*_*ian 148

现有的答案都在讨论从上次提交中删除不需要的文件.

如果要从提交中删除不需要的文件(甚至推送),并且不希望创建新的提交,这是不必要的,因为操作:

1.

找到您希望文件符合的提交.

git checkout <commit_id> <path_to_file>
Run Code Online (Sandbox Code Playgroud)

如果要删除多个文件,可以多次执行此操作.

2.

git commit -am "remove unwanted files"
Run Code Online (Sandbox Code Playgroud)

3.

找到错误添加文件的提交的commit_id ,让我们在这里说"35c23c2"

git rebase 35c23c2~1 -i  // notice: "~1" is necessary
Run Code Online (Sandbox Code Playgroud)

此命令根据您的设置打开编辑器.默认的是vim.

将最后一次提交(应该是"删除不需要的文件")移动到错误提交的下一行(在我们的例子中为"35c23c2"),并将命令设置为fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files
Run Code Online (Sandbox Code Playgroud)

保存文件后你应该很好.

完成 :

git push -f
Run Code Online (Sandbox Code Playgroud)

如果您不幸遇到冲突,则必须手动解决.

  • 如果你想从repo(而不是文件系统)中实际删除文件,而不是仅仅将它们恢复到以前的版本,那么不要执行步骤1来执行`git rm --cached <file(s)>`. (5认同)
  • 通过在`git commit`命令中添加`--fixup = 35c23c2`可以使这个过程更容易一些.这将自动设置提交作为所需提交的修正,因此您不需要在rebase中指定它.另外,如果你将`--autosquash`添加到`git rebase`命令,git会自动将你的提交移动到正确的位置,所以你不需要在交互式rebase中做任何事情 - 只需保存结果(这意味着你甚至不需要`-i`标志,尽管我还是喜欢用它来确保一切看起来像我期望的那样. (5认同)
  • 用纳米做这件事太棒了!Ctrl+K、Ctrl+U,输入“f”,Ctrl+X,输入“y”,瞧! (4认同)
  • 等等你可以随意移动interactive-rebase文件的提交? (2认同)
  • 你完全可以,但你可能(或可能不会)发生冲突. (2认同)
  • 没有用,它在执行 checkout spcific commit 和 file 后什么也不做 (2认同)

Pat*_*ick 118

如接受的答案所示,您可以通过重置整个提交来完成此操作.但这是一个相当沉重的方法.
更简洁的方法是保持提交,只需从中删除更改的文件即可.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit
Run Code Online (Sandbox Code Playgroud)

git reset将文件,因为它是在以前的承诺,并在索引阶段,.工作目录中的文件不受影响.
然后,git commit它将提交并将索引压缩到当前提交中.

这基本上采用了先前提交中的文件版本,并将其添加到当前提交中.这不会导致净更改,因此文件将从提交中有效删除.

  • 对于仅删除单个文件,这是一个更好的解决方案,而不会检修整个提交. (5认同)
  • 这比接受的答案要好 (5认同)
  • 很好的答案,但您可能需要注意一个问题:如果您当前暂存了任何添加或删除的文件,它们将通过“git commit --amend --no-edit”命令添加到提交中。不知道为什么会这样,但它只是咬了我一下。 (2认同)

Par*_*ngh 41

如果您尚未在服务器上推送更改,则可以使用

git reset --soft HEAD~1
Run Code Online (Sandbox Code Playgroud)

它将重置所有更改并恢复为一次提交

如果您已推送更改,请按照@CharlesB所述的步骤进行操作

  • @Aris使用<git diff --cached>来查看更改 (3认同)
  • -1 git reset从暂存区域删除发生的更改文件,此处已提交更改 (2认同)

Bob*_*gon 38

使用rm删除文件将删除它!

你总是在git中添加提交而不是删除,所以在这个实例中将文件返回到第一次提交之前的状态(如果文件是新的,这可能是删除'rm'动作)然后重新提交,文件将继续.

要将文件返回到以前的某个状态:

    git checkout <commit_id> <path_to_file>
Run Code Online (Sandbox Code Playgroud)

或者将其返回到远程HEAD的状态:

    git checkout origin/master <path_to_file>
Run Code Online (Sandbox Code Playgroud)

然后修改提交,你应该发现文件已从列表中消失(并且没有从磁盘中删除!)


小智 35

git checkout HEAD~ path/to/file
git commit --amend
Run Code Online (Sandbox Code Playgroud)

  • 这也改变了文件。如何保留文件中的本地更改? (2认同)

Tha*_*ais 29

以下将仅展示您想要的文件,这是OP所要求的.

git reset HEAD^ /path/to/file
Run Code Online (Sandbox Code Playgroud)

你会看到类似下面的东西......

要提交的更改:(使用"git reset HEAD ..."取消暂停)

修改:/ path/to/file

没有为commit提交的更改:(使用"git add ..."来更新将要提交的内容)(使用"git checkout - ..."来放弃工作目录中的更改)

修改:/ path/to/file

  • "要提交的更改"是提交之前文件的先前版本.如果文件从不存在,这将看起来像删除.如果您提交此更改,则会有一个修订版本将更改恢复为分支中的文件.
  • "未提交的更改"是您提交的更改以及文件的当前状态

此时,您可以对文件执行任何操作,例如重置为其他版本.

当你准备提交时:

git commit --amend -a
Run Code Online (Sandbox Code Playgroud)

或者(如果你还有其他一些你不想提交的修改)

git commit add /path/to/file
git commit --amend
Run Code Online (Sandbox Code Playgroud)

  • juzzlin的答案很棒,但是如果你只是想让一个人停下来,那么它的过分就不会取消整个提交.如果您不希望丢失该提交中的文件的当前未分级更改,则取消暂存整个提交可能会导致问题. (3认同)

Moa*_*had 23

我将以实例向您解释.
设A,B,C为3次连续提交.提交B包含一个不应提交的文件.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    
Run Code Online (Sandbox Code Playgroud)


Dev*_*vWL 15

将文件保留在本地(从 gi​​t commit 中删除)

如果你想保留该文件,你可以--cached像这样使用:

git rm --cached filename
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

删除本地文件(并从 git commit 中删除)

否则,如果你想删除该文件,只需使用:

git rm filename
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


小智 13

如果您不小心将文件添加到提交中,则可以执行以下操作

git rm --cached path_to_file
Run Code Online (Sandbox Code Playgroud)

确保使用--cached否则文件也将从项目中删除。


Bry*_*ley 12

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"
Run Code Online (Sandbox Code Playgroud)

将保留本地文件.如果您不想在本地使用该文件,则可以跳过--cached选项.

如果所有工作都在您的本地分支上,您需要将文件保留在以后的提交中,并且就像拥有干净的历史记录一样,我认为更简单的方法可能是:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^
Run Code Online (Sandbox Code Playgroud)

然后,您可以轻松完成rebase,而无需记住更复杂的命令或提交消息或输入更多内容.


JDi*_*teo 10

使用git GUI可以简化从先前提交中删除文件的过程.

假设这不是共享分支,并且您不介意重写历史记录,那么运行:

git gui citool --amend
Run Code Online (Sandbox Code Playgroud)

您可以取消选中错误提交的文件,然后单击"提交".

在此输入图像描述

该文件将从提交中删除,但将保留在磁盘上.因此,如果您在错误地添加文件后取消选中该文件,它将显示在您未跟踪的文件列表中(如果您在错误地修改文件后取消选中该文件,则会在您的更改中显示未提交的提交列表).

  • 在Ubuntu上,你可以使用`sudo apt-get install git-gui`安装git gui (2认同)

mat*_*exx 9

如果你想保留你的提交(也许你已经花了一些时间编写一个详细的提交消息而不想丢失它),你只想从提交中删除文件,而不是完全从存储库中删除:

git checkout origin/<remote-branch> <filename>
git commit --amend
Run Code Online (Sandbox Code Playgroud)


Min*_*yen 6

git reset --soft HEAD~1. 
Run Code Online (Sandbox Code Playgroud)

这将撤消本地存储库中的最后一次提交,并将所有内容移回舞台区域,就像执行提交之前一样。然后,只需正常使用任何 Git UI 工具(如 TortoiseGit、Git UI、Git Extensions...)来取消暂存我们不想提交的文件,然后再次提交。


cri*_*fan 6

  1. git reset --soft HEAD~1
  2. git reset HEAD /file/to/delete
  3. git rm --cached /file/to/delete
  4. git commit --amend -m "your message"
  • 关键点是--amend

然后可以:

git push -u origin master


Ser*_*nko 5

执行以下命令序列:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'
Run Code Online (Sandbox Code Playgroud)


and*_*epo 5

只是想补充最重要的答案,因为我必须运行一个额外的命令:

git reset --soft HEAD^
git checkout origin/master <filepath>
Run Code Online (Sandbox Code Playgroud)

干杯!


wil*_*087 5

如果要从以前的提交中删除文件,请使用过滤器

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'
Run Code Online (Sandbox Code Playgroud)

如果您看到此错误:

无法创建新备份。以前的备份已存在于 refs/original/ 中,用 -f 强制覆盖备份

只需删除本地存储库上的 refs 备份

$ rm -rf .git/refs/original/refs
Run Code Online (Sandbox Code Playgroud)