我在从Git

时间:2017-12-05 11:06:51

标签: git commit gitk

目前我的回购图如下图所示:

enter image description here

我需要删除前3个提交,因为它们是错误的自动化流程的产物。我想真的删除那些提交,以便我可以摆脱他们的文件混乱回购。其中一个提交对代码进行了2000多次不正确的修改,我想删除这3个提交和GC他们的工件。

为此,我运行了这些命令:

git reset --hard 3e2fb0bcd1471d33c940a4da3809ce6c48dd1c32
git push -f origin master

这让我走得很远:

enter image description here

这是我的预期。但是,我有两个问题:

1)那些提交仍然存在。它们不是代码库历史的一部分;他们是个错误,我不想让他们留在回购中。如何从回购中完全删除它们?

2)当我跑步时

git pull origin master

repo恢复到图像1中描述的状态。虽然我已经同步了本地和远程回购!为什么会这样?如何确保提交3e2fb0 ...是“最新”提交?

1 个答案:

答案 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。