目前我的回购图如下图所示:
我需要删除前3个提交,因为它们是错误的自动化流程的产物。我想真的删除那些提交,以便我可以摆脱他们的文件混乱回购。其中一个提交对代码进行了2000多次不正确的修改,我想删除这3个提交和GC他们的工件。
为此,我运行了这些命令:
git reset --hard 3e2fb0bcd1471d33c940a4da3809ce6c48dd1c32
git push -f origin master
这让我走得很远:
这是我的预期。但是,我有两个问题:
1)那些提交仍然存在。它们不是代码库历史的一部分;他们是个错误,我不想让他们留在回购中。如何从回购中完全删除它们?
2)当我跑步时
git pull origin master
repo恢复到图像1中描述的状态。虽然我已经同步了本地和远程回购!为什么会这样?如何确保提交3e2fb0 ...是“最新”提交?
答案 0 :(得分:0)
[git reset --hard <hash>
和git push -f origin master
成功,但是
1)那些提交仍在那里。
是。这些承诺是永久性的。这三个哈希ID表示这三个提交,反之亦然。在Git中做的是为那些提交带来你自己的名称(git reset
改变你的master
,这样它就不会命名这三个哈希ID中的一个),然后带走其他人的名称(git push -f origin master
),以便他们的 master
不会将其中一个列为哈希的ID。
(我不知道哈希ID,或者我会在这里使用。哈希ID是&#34;真实名称&#34;提交;名称如master
只是符号允许我们或Git找到一个特定的提交,其父代找到更多的提交,其父母找到更多的提交,依此类推。这就是&#34;可达性&#34;的想法:提交通过此父级跟踪进程可以从名称访问<注意任何名称将在存储库中执行&#34; alive&#34;。是不可达的,不是很活跃:它要么在最终死亡的过程中,要么在被创造的过程中。)
您自己的远程跟踪名称origin/master
保留旧的哈希ID,直到您运行git push -f origin master
。当你的Git看到他们的Git已接受名称更新时,你的Git更新了他们的名字副本。这消除了您对该哈希ID的第二个名称。如果那是所有你的名字,那么你的名字就足够了。
如果origin
处的Git只有一个名称,使这三个提交可以访问,那个名称为master
,则您已更新 Git / repository,以便它不再具有这些提交的任何名称。
此时的真正问题是:其他 Git存储库对于这三个哈希ID中的一个具有其他名称?
......他们错了,我不想让他们留在回购中。如何从回购中完全删除它们?
一般来说,你不会:这通常是徒劳的。从任何名称分支或标记名称或其他Git内部名称无法访问的提交最终将过期并被垃圾收集&#34;。 这个是让提交真正消失的原因。但是,在此之前,任何拥有哈希ID的人都可以通过哈希ID查找提交。
如果没有其他Git选择了这三个哈希ID,那么您已从受影响的两个哈哈ID中删除了这三个哈希ID的可访问性存储库,这是你真正需要的。
如果其他人 进行了三次提交,那么其他Git可以将它们(通过哈希ID和建议的名称)提供给您的Git和/或您调用的Git {{1} }。作为Gits,你的Git和起源Git很可能会在Borg fashion,&#34;你的技术独特性将被添加到我的存储库&#34;并再次带他们进去。永远摆脱承诺是非常困难的,因为一旦它被制造出来,Git真的不想摆脱它。
2)当我跑步时
origin
repo恢复到图像1中描述的状态。虽然我已经同步了本地和远程回购!为什么会这样?我如何确保提交3e2fb0 ...是最新的&#39;提交?
如果您自己的git pull origin master
成功,但后来git push -f origin master
将三次提交恢复,则意味着git pull origin master
上的Git决定其origin
应指向这三个提交中的大多数提示。
会发生什么?好吧,假设有一个第三个 Git具有这三个提交,并且可能是其中一个提交的名称。第三个Git的用户运行master
甚至git push <url> <name>:master
。这使得他们(第三个)Git在git push <url> <hash-id>:master
调用Git,这是你调用{4}的Git,并通过其哈希ID向它提供特定提交。
<url>
处的Git获取该哈希ID(并在必要时重新获取提交本身,如果它已设法对从中获取的副本进行垃圾收集)并查看其父ID,并且父母&#39;父ID等,并查看它是否可以将其提交的技术独特性添加到其存储库中。果然,它可以:这三个提交很容易插在自己的origin
之上!所以origin
的Git接受这些提交,将它们添加到其存储库,并更新其master
以指向最尖端的提交。
这使得摆脱这些事情变得如此困难。一旦提交,提交很容易适合存储库的每个克隆,因为它与至少一个克隆匹配。每个调用另一个Git的Git都会得到它最新提交的副本,这些提交像病毒一样通过Git的Borg-ness技术获取。
真的,真的,摆脱提交,你必须在你的存储库中无法访问它 在所有其他存储库中无法访问< / em>以便这些Gits都不会在任何时候将它提供给任何其他Git。否则,就像一些顽固的病毒一样,它会不断回归。
如果每个人都认为某些中央存储库是真实的来源,那么 例如,假设您调用的origin
的Git位于您自己的主服务器上,或者甚至位于GitHub或Bitbucket或其他某个分发点上,和您对的充分控制< / em> server / Git。您可以通过其哈希ID或其他一些技巧安排 Git 拒绝错误提交。
&#34;拒绝哈希ID&#34;是最简单的。例如,您可以在master
处为该特定Git存储库创建或调整服务器上的预接收或更新挂钩。让存储库检查传入的origin
操作是否会使任何不需要的哈希ID变得可访问。如果是这样,拒绝推送。使用origin
人可以阅读和理解的消息:&#34;提交XXXXX是一个错误,请使用git reset将其从您自己的Git中删除;请通过&lt; url&gt;与我们联系如果出现混淆&#34;。
稍微复杂且容易出错,您可以重置自己的push
以使不受欢迎的提交 un 无法访问,然后在其上面进行新的提交。然后git push
将结果master
发送给git push -f
。现在,如果某个第三个Git用户运行origin
来发送原始的三个提交,他们就会轻松地赢得插槽。该用户也必须强制-push。
你会遇到的问题是,一些天真的用户会想:哦,我应该 rebase 让我的代码插槽更容易! {{1} }命令复制旧的提交,例如,不要直接插入,以便它们成为新的提交新的哈希ID 做git push origin存储库。
即使使用&#34;拒绝哈希ID&#34;仍然可能发生这种情况。技术,但至少你有一个强烈措辞的信息,所有用户都会阅读和理解。 (咳嗽)
最复杂的方法是对原始哈希ID 和 rebase复制版本的证明,就是编写一个预接收或更新挂钩,通过一些独特的东西来识别坏提交坏:不仅仅是哈希ID本身,而是与提交相关的内容更突出的东西。也就是说,人们会像变异病毒一样处理不良提交,找到一个适当的签名,表明提交中包含待拒绝的病毒,并拒绝它。
当然,所有这些方法都要求您在git rebase
处充分控制Git。