更改提交到GitHub的提交...删除文件

时间:2019-02-07 13:54:56

标签: git commit amend

Git扭曲了我的大脑。但是我认为这个问题已经解决了一半。

我提交(两次)并推送到GitHub,但是第一次提交包含两个不应包含的文件。所以我做了以下...

git reset --hard HEAD~2

这使HEAD返回带有额外文件的第一次提交。

HEAD is now at 1979096c2

现在,如果我仅使用所需的两个文件进行修改,再次提交(并强制推送),这是否可以在GitHub上更正提交?

更清楚地说...初始(错误)提交包含4个文件。我想将其修改为只有2个文件。我在正确的轨道上吗?

3 个答案:

答案 0 :(得分:0)

您说得对,这将解决问题。尽管您基本上是在重写历史记录,但请小心用力。撤消了您将要删除的那些提交的任何人都将从远程发散。如果您是回购或分支机构中唯一的工作人员,那没关系。

答案 1 :(得分:0)

除了进行硬重置外,您还可以执行git revert。

git revert <commit_id>

使用 git log 来引用您要还原的提交ID。

答案 2 :(得分:-1)

不。

首先,当您说“修改,提交(和强制推送)”时,您是指git commit --amend命令吗? amend选项的命名可能会有些混乱。尽管它确实反映了命令的目的,但它建议它编辑现有的提交,而不编辑它,因为这是不可能的。

重置后的状态如下

O <--(master)
 \
  A -- B <--(origin/master)

因此,您两次提交了{AB),但是A包含了您不想在存储库中使用的文件,因此您将2次提交重置为(之前的 A)。那么首先要了解的是,如果您从此处进行commit --amend,它将修改提交O-而不是提交A

但是,鉴于我如上所述,您不能更改现有的提交,“修改”提交是什么意思?好吧,这意味着您将创建一个新提交-具有新ID-并用它“替换”旧提交。这听起来像是在分裂头发,但这很重要,因为“替换”提交并不能完成您可能会想到的所有事情。

假设您重置为提交A。在所描述的示例中,这将是git reset --hard master^(分支尖端之前的1个提交-因此,您已签出“错误”的提交)。现在你有

O -- A <--(master)
      \
       B <--(origin/master)

现在,您可以编辑工作树(即删除不需要的文件),然后可以告诉git“修改”提交A。但是你会得到的是

O -- A -- B <--(origin/master)
 \
  C <--(master)

C是具有新ID的新提交。如果您仅在commit --amend之前进行了少量更改,则相对于O,它与A的应用主要相同,但仍然完全独特的提交。在您本地分支机构的历史记录中,C替换了A-但在您本地分支机构中仅 -而不是整个存储库。 B仍将A视为其父项,而origin/master仍指向B

如果然后强行推动,则将origin/master移至C。这是一个历史记录编辑,如果存储库与他人共享,则将产生后果。请参阅“从上游基础恢复中”下的git rebase文档;本节适用于任何重写,无论它是否涉及rebase命令。还要注意,如果您没有正确地与回购的其他用户协调强制推送,那么他们中的任何一个在恢复和撤消所做的更改时可能会做错事。

因此,除了用A替换C之外,此过程还从分支历史中删除B,因为用A“替换” C并不是在整个存储库中进行就地替换。

您可以通过将BA重新定为C来解决此问题。有几种解决方法,例如

git checkout origin/master
git rebase --onto master HEAD^

这给你

O -- A -- B <--(origin/master)
 \
  C -- B' <--(master)

这里,我使用了一种表示法,表示相对于新的基础,新的提交(B')与旧的提交(B)具有相同的更改-但这仍然是完全新提交。同样,这是历史记录的重写,您必须与任何其他用户协调并强制推送。

根据为什么要从存储库中排除这些文件的原因,可能还很重要的一点是要知道这实际上还没有删除原始历史记录(包括已删除的文件)。只要旧的历史记录保留在reflog中,您的本地回购协议将至少保留它们。您可以采取一些步骤在本地执行更早的清理;但是远程服务器(取决于其托管方式)可能具有或不具有从中删除文件的便捷过程。而且您无能为力,不能保证从可能存在的任何其他克隆中删除文件。

因此,如果文件包含敏感信息(并且其他任何人都可以访问遥控器),则需要将该信息视为已泄露。如果文件很大,则可以搜索现有问题和答案,详细说明如何从历史记录中清除它们以恢复空间