Git扭曲了我的大脑。但是我认为这个问题已经解决了一半。
我提交(两次)并推送到GitHub,但是第一次提交包含两个不应包含的文件。所以我做了以下...
git reset --hard HEAD~2
这使HEAD返回带有额外文件的第一次提交。
HEAD is now at 1979096c2
现在,如果我仅使用所需的两个文件进行修改,再次提交(并强制推送),这是否可以在GitHub上更正提交?
更清楚地说...初始(错误)提交包含4个文件。我想将其修改为只有2个文件。我在正确的轨道上吗?
答案 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)
因此,您两次提交了{A
和B
),但是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
并不是在整个存储库中进行就地替换。
您可以通过将B
从A
重新定为C
来解决此问题。有几种解决方法,例如
git checkout origin/master
git rebase --onto master HEAD^
这给你
O -- A -- B <--(origin/master)
\
C -- B' <--(master)
这里,我使用了一种表示法,表示相对于新的基础,新的提交(B'
)与旧的提交(B
)具有相同的更改-但这仍然是完全新提交。同样,这是历史记录的重写,您必须与任何其他用户协调并强制推送。
根据为什么要从存储库中排除这些文件的原因,可能还很重要的一点是要知道这实际上还没有删除原始历史记录(包括已删除的文件)。只要旧的历史记录保留在reflog中,您的本地回购协议将至少保留它们。您可以采取一些步骤在本地执行更早的清理;但是远程服务器(取决于其托管方式)可能具有或不具有从中删除文件的便捷过程。而且您无能为力,不能保证从可能存在的任何其他克隆中删除文件。
因此,如果文件包含敏感信息(并且其他任何人都可以访问遥控器),则需要将该信息视为已泄露。如果文件很大,则可以搜索现有问题和答案,详细说明如何从历史记录中清除它们以恢复空间