【问题标题】:Is nothing truly ever deleted in git?git中真的没有删除任何东西吗?
【发布时间】:2011-06-01 07:54:24
【问题描述】:

我目前正在学习 git,通常我对 VCS 有点怀疑,因为我很难习惯它们。

我删除了一个名为“experimental”的分支,其中包含一些 tmp 文件,我看到这些文件在我的工作目录中被删除,所以我挠了挠头,想知道这是否正常,我可以把它拿回来以备不时之需,等等.

我发现 SHA 提交了 tmp 文件,并使用提供的 sha 重新创建了分支,并再次查看了所有文件及其当前内容。

我在工作目录中所做的一切都可以在我提交后还原吗?

对很多人来说可能是一个愚蠢的问题,但它有点吸引我,所以我想知道限制

【问题讨论】:

    标签: git


    【解决方案1】:

    如果您已对文件提交了相应的更改,几乎所有操作都可以撤消。即使您强制删除分支或进行硬重置,您也可以使用 git refloggit fsck 找到松散的提交对象。

    不过,松散的物体偶尔会被git gc清理掉,过一段时间就无法恢复了。

    【讨论】:

    • 您必须故意为git gc 设置较低的gc.pruneexpire 设置以立即修剪无法访问的对象。您的最后一句话暗示手动运行git gc 可能很特别。
    • @Charles:我改写了最后一句话。你是对的,我并不是说手册git gc 会立即修剪松散的物体。我只是想注意git gc自动运行,但也可以手动运行。
    • 这个答案是否仅适用于本地 git 存储库,或者在推送时也适用于远程(例如,在集中式远程的情况下)?
    • @nha 我所知道的“本地”和“远程”(共享)存储库之间的唯一主要区别是后者通常是裸露的,即不包含工作副本,但这应该没有区别上面讨论的内容。
    【解决方案2】:

    任何严肃的 VCS 的要点都是以永久和不可变的方式保存项目的整个历史。因此,您可以随时对您的工作进行任意修订。

    git 在存储方面有一个特殊的行为,如果没有对它的引用,它可以删除对象。参考文献是:

    • 一个分支的每个 HEAD
    • 标签(我不确定未引用的带注释标签是否仍然充当活动引用)
    • 每个提交都被另一个提交引用
    • 分支引用日志的内容

    这意味着所有作为分支的一部分的提交都被保留,每个被标记的对象(=大部分提交)也被保留。每个分支上还有一个所谓的 reflog(除非停用),其中 git 保留对您在过去几天创建的所有对象的引用。当一个对象未​​被任何分支、标签或 reflog 引用时,git gc 会将其从数据库中删除。这是典型的情况,您创建了一个黑客分支,在那里提交了一些东西,然后删除了这个分支而不将它合并到另一个分支中。

    【讨论】:

      【解决方案3】:

      我在工作中所做的一切 一旦我可以恢复目录 提交吗?

      是的,你可以。例如,试试git reflog。这会给你一个提交的列表 在当前分支上。按其 sha1 总和选择一个,然后键入 git checkout 45db2a...。这检查了该提交。如果您想进行更改,请务必从那时起git checkout HEADgit checkout -b newbranch

      您还可以使用 git 在您当前的 HEAD 之上挑选这些提交(即,如果它们是在不同的分支中完成的,您可以将它们拉入)。 This question 讨论得比我好得多。

      【讨论】:

      • 在查看了答案后,我有点明白了,这有点令人困惑,但在推/拉到服务器时差别不大(至少对我来说是这样)。现在,我不知道是在 stackoverflow 还是在这里问,但是为什么“git rm”dry-run 不起作用?我不得不删除我的整个目录以将其反映在私人服务器中。我想保留我的文件并删除服务器上的文件
      • 啊,我明白了。您可以通过执行以下操作强制从远程存储库中删除分支:git push remotename :branchname(奇怪的语法,git push branchname 推送它。区别只是:)。我不知道你是否可以使用单独的提交来做到这一点,这是一个有趣的问题。
      【解决方案4】:

      git reset --hard 可以不可逆地删除更改

      【讨论】:

      • @3lectrologos 嗯,有趣...我如何撤消硬重置?
      • 我认为@3lectrologos 处于“一旦我提交”状态。
      • @3lectrologos:公平地说,使用git reset --hard 丢弃工作树更改是git reset 的一种非常常见的用法,因此从干净状态开始并不是git reset 的全部内容。
      • @J-16 SDiZ:我更喜欢git reset --hard HEAD@{1};至少它对时间不敏感。
      • @Charles:是的,这很常见。但是,这样的答案具有误导性,因为它没有关注丢弃工作树更改的不可逆性(使用git checkout -- filesgit resetgit clean),而是给人留下了特别是git reset --hard 的印象是不可逆转的动作。
      猜你喜欢
      • 1970-01-01
      • 2020-10-24
      • 2012-12-22
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      • 2023-02-02
      • 2016-11-14
      • 1970-01-01
      相关资源
      最近更新 更多