Version control 有没有办法删除Mercurial中单个文件的历史记录?

Version control 有没有办法删除Mercurial中单个文件的历史记录?,version-control,mercurial,dvcs,Version Control,Mercurial,Dvcs,我想我已经知道了答案,但我想我还是会问: 我们有一个添加到Mercurial存储库的文件,其中包含敏感信息。是否有任何方法可以在不删除整个回购的情况下删除该文件及其更改历史记录?不,您不能。阅读mercurial红皮书中关于它的部分;特别是包含本段的小节: Mercurial也没有提供一种方法 使文件或变更集完整 从历史中消失,因为有 没有办法执行它的命令 消失有人很容易 将他们的Mercurial副本修改为 忽视这些指令。此外 即使Mercurial提供了这样的 能力,一个根本没有能力的人 拉

我想我已经知道了答案,但我想我还是会问:

我们有一个添加到Mercurial存储库的文件,其中包含敏感信息。是否有任何方法可以在不删除整个回购的情况下删除该文件及其更改历史记录?

不,您不能。阅读mercurial红皮书中关于它的部分;特别是包含本段的小节:

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


mercurial通过
backout
命令(同样,mercurial book:)支持恢复提交的更改的常用方法,但信息不会从存储库中消失:因为您永远不知道是谁克隆了您的存储库,这会产生错误的安全感,如上所述。

,然后hg strip从Mercurial中删除特定文件是正确的,因为这样做会破坏存储库中的所有变更集ID。当您更改变更集ID时,每个人都必须重新克隆存储库。有关在Mercurial中修改历史记录的后果的信息,请参见


如果这对您(公司的内部存储库)没有问题,那么请查看。它可以做hg→ hg转换,并具有一个--filemap参数,该参数可用于排除文件等。

可以在本地执行,但不能在全局执行,它会在添加文件后更改每次提交的ID。为了使更改保持不变,您需要访问存储库的每个副本,特别是从中提取或推送的副本

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

  • .hgrc
    中启用MQ扩展:

    [extensions]
    mq =
    
  • 从上游拉动最近的变化

    hg pull
    
    hg push -f
    
  • 将从文件添加开始的所有内容导入MQ:

    hg qimport -r 1301:tip
    hg qpop -a
    
  • 从添加该文件的提交中删除该文件

    hg qpush 1301.diff
    hg forget path/to/badfile.cfg
    hg qrefresh
    
  • 将修补程序转换为新的Mercurial修订版

    hg qpush -a
    hg qfinish -a
    
    hg strip 5200a5a10d8b
    
  • 将新修订推到上游

    hg pull
    
    hg push -f
    
  • 在上游存储库中和每一个其他副本上,删除旧版本

    hg qpush -a
    hg qfinish -a
    
    hg strip 5200a5a10d8b
    
  • 警告:除非您小心,否则此步骤可能会破坏工作。如果自上次你从上游撤离后,有人做出了任何承诺,那么你必须在剥离之前重新确定该工作的基础。不幸的是,
    rebase
    扩展在这里没有帮助;您必须再次使用MQ,将新提交转换为应用于新提示的补丁


    祝你好运。

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

    如何:使用hg转换,如中所述。基本上,您可以将一个Hg repo“转换”为一个新的Hg repo,但您需要指定一个在转换过程中要排除的文件列表。这是关键步骤的摘录:

    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都将不同
    • 新的“干净”主存储库必须手动放置以取代现有的存储库
    • 所有团队成员都必须对主回购协议进行新的克隆
    • 与Hg集成的任何其他服务可能需要注意(例如,问题追踪器、代码审查系统等)

    该文件几乎贯穿了整个更改历史。您能否详细介绍如何使用上述命令从repo中清除文件历史记录,同时保留其他文件的更改历史记录?您不能使用移植从变更集中删除单个文件--移植只知道如何将整个变更集从一个分支或存储库移到另一个分支或存储库(类似于hg导出| hg导入). 请参阅我关于转换扩展的回答。请参阅,了解如何处理某个Mercurial版本中的问题。感谢Martin,他拯救了一个充满已编译二进制对象的庞大存储库。拯救了这一天!是的,你们可以:当然你们所有人都必须重新申报回购协议,但你们并没有失去整个历史。虽然这是公认的答案,但这不是正确的答案@wrzasa在评论中引用了正确的答案。我个人使用该链接中的信息多次完成了OP要求的操作。我必须
    hg-phase-secret-force 1301
    ,然后才能像魅力一样工作。有趣。不过,看起来阶段有点不同,隐藏整个提交,而不是从提交中删除文件。他们也可能不会删除或隐藏上游存储库的提交。这个答案对我很有帮助,即使它不是“删除”,而是将repo转换为自身(并且您会丢失所有变更集ID):这对我来说没有问题。请注意,即使在windows上,排除文件名也区分大小写。