将删除提交删除对象仓库

时间:2017-11-01 21:44:33

标签: git

在git中删除提交真的有用吗?我会松一些变化吗?它实际上不应该因为每次提交都将拥有工作目录的整个快照。那应该不是问题??

我正在考虑恢复合并。我发现每个人都在谈论重新合并合并提交将不会从原始合并中获得更改。

修改

这是上下文.. https://www.reddit.com/r/git/comments/2w0qpb/redo_a_merge_after_reverting_it/

它谈论失去了99个变化......什么是关于失败..每次都是一个快照......我想问题是,提交中保存了什么以及当它播放时会发生什么它(在樱桃挑选或变种的情况下)......

最新提交不足够吗。

2 个答案:

答案 0 :(得分:1)

提交是给定时间内整个存储库的快照。它包括:

  • 指向包含repo状态的树对象的指针 - 其他树,blob(文件)

  • 元数据 - 介绍了变更等等。

  • 指向父母的指针

  • 识别信息

此提交对象存储在.git / objects中。我强烈建议不要直接修改它。

git revert将引入与给定提交的更改相反的更改(在您的情况下是最后一次,合并提交,即HEAD)。现在这实际上是一个新的提交本身。 听起来,这不是你所追求的。相反,它听起来像你想从合并提交中删除然后再次合并。

你可以这样做:

git reset HEAD~1

这会将HEAD指针返回到合并前的状态。原始合并提交引入的任何更改仍将位于工作目录中。要摆脱这些,你可以做到

git reset --hard

现在,合并提交仍会存在一段时间。如果需要通过参考ref日志

,您可以检索指向它的指针
git log -g 

最终,此提交将被垃圾收集。

答案 1 :(得分:0)

您实际上删除提交。与在Svetlomir Hristozkov's answer中一样,您可以将其重置为"所以当前分支提示不是reachable。如果无法从所有外部引用(包括reflog引用)访问它,git gc通常会在此时将其抛出。

我发现整个事情在Mercurial中更容易解释,您可以在其中运行hg strip -r <rev>以删除修订版<rev> 及其所有后代。你必须在Git中做同样的事情,因为提交变得无法访问,因为每个后代提交(子,孙子,曾祖母等)编码,作为其Merkle-tree的一部分 - 形成哈希ID,要删除的提交的哈希ID。所以你必须丢弃提交的所有后代。如果你想保留那些后代 - 这是大多数人所做的 - 你必须&#34;嫁接&#34;这些快照及其元数据的新副本到一个新的后代链中,这些后代来自您想要的提交的父级&#34;剪掉&#34;。

在Git中执行此操作的主要方法是使用git filter-branchgit filter-branch命令只是复制每个提交(或者更确切地说,根据引用名称和您提供的其他限制器作为参数,在存储库的某些受限子集中的每次提交)。为了制作副本,它:

  1. 提取原文;
  2. 按顺序应用每个过滤器;和
  3. 提交结果。
  4. 如果新提交与原始提交一点一点地相同,则它们将使用相同的哈希ID。如果任何位发生更改,则新提交具有新的不同哈希ID,并且该新ID将作为后续子项的父项的输入。

    git filter-branch从提交移动到提交时,它会构建一个&#34;旧的哈希ID&#34;到最近适当的新哈希ID&#34;。此映射是在复制操作期间可以如何修改要剪切或以其他方式修改的提交的子项。

    --parent-filter允许您对父哈希ID进行任意更改,--commit-filter可以故意跳过提交。有关详细信息,请参阅the documentation。但是,请注意git filter-branch服从git replace创建的替换对象,因此您可以使用git replace拼接出一些提交,然后根据需要使用no-op {{1在遵守替换时复制所有内容,有效地形成一个缺少拼接提交的新提交图。

    执行此操作并指示git filter-branch更新相应的外部引用(主要是分支名称和标记)后,您将拥有一个新的存储库,其中省略了您想要省略的提交。

    git filter-branch中存在一个缺陷,因为它对git filter-branch没有任何用处。默认情况下,git notes命令将复制备注。对于某些有限的情况,可以使用复制提交的交互式rebase删除提交 - 但由于目标不同,git rebase使用git rebase制作副本,这不会像git cherry-pick那样表现。