【问题标题】:Is there a way to remove the history for a single file in Mercurial?有没有办法删除 Mercurial 中单个文件的历史记录?
【发布时间】:2009-06-22 21:24:51
【问题描述】:

我想我已经知道了这个问题的答案,但我还是想问一下:

我们有一个文件被添加到 Mercurial 存储库中,其中包含敏感信息。有没有办法在不删除整个仓库的情况下删除该文件及其更改历史记录?

【问题讨论】:

标签: version-control mercurial dvcs


【解决方案1】:

您不能轻易地从 Mercurial 中删除特定文件是正确的,因为这样做会破坏存储库中的所有变更集 ID。当您更改变更集 ID 时,每个人都必须重新克隆存储库。有关在 Mercurial 中修改历史记录的后果的信息,请参阅 Wiki page about editing history

如果您觉得可以(公司的内部存储库),请查看convert extension。它可以进行 hg → hg 转换,并有一个 --filemap 参数,可用于排除文件等。

【讨论】:

  • 请参阅stackoverflow.com/questions/10103227/… 以处理某个 Mercurial 版本中的问题。
  • 感谢 Martin,拯救了一个充满已编译二进制对象的庞大臃肿的存储库。拯救了这一天!
【解决方案2】:

不,你不能。阅读 mercurial red book 的 changes that should have never been 部分了解它;尤其是 what about sensitive changes that escape 小节,其中包含以下段落:

Mercurial 也没有提供方法 完全制作文件或变更集 从历史中消失,因为有 是没有办法执行其 消失;有人可以很容易 将他们的 Mercurial 副本修改为 忽略此类指令。此外, 即使 Mercurial 提供了这样的 能力,一个根本没有的人 拉了一个“让这个文件消失” 变更集不会受到它的影响, 网络爬虫也不会访问 错误的时间、磁盘备份或其他 机制。确实,没有分布式 修订控制系统可以制作数据 可靠地消失。提供 这种控制的错觉很容易 给人一种虚假的安全感, 比根本不提供更糟糕。

mercurial 通过backout 命令(同样,mercurial book:dealing with committed changes)支持恢复已提交更改的常用方法,但信息不会从存储库中消失:因为你永远不知道谁确切地克隆了你的存储库,如上所述,这会给人一种虚假的安全感。

【讨论】:

  • 是的,您可以:jitbit.com/alexblog/232-removing-files-from-mercurial-history 当然,你们所有人都必须重新克隆您的存储库,但不要丢失整个历史记录。
  • 虽然这是公认的答案,但它不是正确的答案。 @wrzasa 在他的评论中引用了正确的答案。我已经使用该链接中的信息亲自完成了 OP 多次询问的内容。
【解决方案3】:

它可以在 10 分钟内完成。在单个存储库中,尽管有后果。

如何:按照this excellent guide 中的说明使用 hg convert。基本上,您将 Hg 存储库“转换”为新的 Hg 存储库,但您可以指定在转换期间要排除的文件列表。这是关键步骤的摘录:

Make sure all your teammates have pushed their local changes to the central repo (if any)
Backup your repository
Create a "map.txt" file:

# this filemap is used to exclude specific files
exclude "subdir/filename1.ext"
exclude "subdir/filename2.ext"
exclude "subdir2"

Run this command:
hg convert --filemap map.txt c:/oldrepo c:/newrepo
NOTE: You have to use "forward-slash" in paths, even on windows.
Wait and be patient
Now you have a new repo at c:\newrepo but without the files

至于后果……

  • 添加要排除的文件后的所有变更集 ID 都将不同
  • 新的“干净”主存储库必须手动替换现有的主存储库
  • 所有团队成员都必须对主 repo 进行新的克隆
  • 与 Hg 集成的任何其他服务可能需要注意(例如问题跟踪器、代码审查系统等)

【讨论】:

  • 这对我有用,没有问题。请注意,即使在 Windows 上,排除文件名也区分大小写。
【解决方案4】:

在本地是可能的,但不是全局的,它会在添加文件之后更改每个提交的 ID。为了使更改生效,您需要访问存储库的每个副本,尤其是从中提取或推送的副本。

也就是说,我已经按照 Mercurial wiki 上描述的Editing History 序列从我的一个存储库中删除了一个文件。此序列假定修订版 1301:5200a5a10d8b 添加了文件 path/to/badfile.cfg,该文件在任何后续修订版中均未更改:

  1. .hgrc 中启用 MQ 扩展:

    [extensions]
    mq =
    
  2. 从上游拉取最近的更改。

    hg pull
    
  3. 将文件添加后的所有内容导入 MQ:

    hg qimport -r 1301:tip
    hg qpop -a
    
  4. 从添加它的提交中删除文件。

    hg qpush 1301.diff
    hg forget path/to/badfile.cfg
    hg qrefresh
    
  5. 将补丁转换为新的 Mercurial 修订版。

    hg qpush -a
    hg qfinish -a
    
  6. 将新修订推送到上游。

    hg push -f
    
  7. 在上游存储库和其他所有副本中,删除旧版本。

    hg strip 5200a5a10d8b
    

警告:除非您小心,否则此步骤可能会破坏工作。如果自您上次从上游拉出以来有人已经提交了任何内容,那么您必须在剥离之前重新调整该工作。不幸的是,rebase 扩展在这里没有帮助;您将不得不再次使用 MQ,将新提交转换为您应用到新提示的补丁。

祝你好运。

【讨论】:

  • 我必须 hg phase --secret --force 1301 才能发挥作用。
  • 有趣。不过,看起来阶段有点不同,隐藏整个提交而不是从提交中删除文件。他们也可能不会删除或隐藏上游存储库的提交。
【解决方案5】:

hg移植,然后hg剥离

【讨论】:

  • 该文件几乎涵盖了整个更改历史记录。您能否详细说明如何使用上述命令从存储库中清除文件历史记录,同时保留其他文件的更改历史记录?
  • 您不能使用移植从变更集中删除单个文件——移植只知道如何将整个变更集从一个分支或存储库移动到另一个(就像 hg export | hg import)。请参阅我关于转换扩展的答案。
猜你喜欢
  • 2011-02-10
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 1970-01-01
  • 2015-07-24
相关资源
最近更新 更多