Git 从另一个存储库的上一个文件启动新存储库

Git 从另一个存储库的上一个文件启动新存储库,git,Git,我在一个存储库分支中有一个文件,我希望在它自己的存储库中有一个文件,用它来构建一个包 /A -file1 -file.code -file3 -.git 我想要: /B -file.code -.git #with all the previous history for such file /A -file1 -file3 -.git 我想保留我对这个文件所做的提交的历史记录,并且能够在主项目中继续使用它,这样在完成包之前不会丢失功能 我认为这与我想做的类似,一些评论建议

我在一个存储库分支中有一个文件,我希望在它自己的存储库中有一个文件,用它来构建一个包

/A
 -file1
 -file.code
 -file3
 -.git
我想要:

/B
 -file.code
 -.git #with all the previous history for such file
/A
 -file1
 -file3
 -.git
我想保留我对这个文件所做的提交的历史记录,并且能够在主项目中继续使用它,这样在完成包之前不会丢失功能

我认为这与我想做的类似,一些评论建议使用子模块,如中所示,问题是保留所有原始历史

我还发现,当我尝试主要答案时,哪个不起作用,我得到了断言错误和:

$git clone file.code ../folder
Cloning into '../folder'...
fatal: Invalid gitfile format: path/to/file.code
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
我的另一个解决方案解决了目录和移动到现有存储库时的问题(并不是说创建一个新的空存储库很麻烦),但它不适用于单个文件

最后,我考虑从一个存储库“移动”到另一个存储库,但是

$git mv file.code ../B
fatal: ../B: '../B is outside repository

如何移动/克隆/。。。将现有文件保存到新存储库中,并保留其所有历史记录?

在Git中,文件没有历史记录

相反,提交具有历史记录,或者更准确地说,提交就是历史记录。而且,提交有文件。但是文件没有历史记录。因此,如果您想要历史记录,那么您需要的是提交,这些提交将带来文件

filter branch
命令将允许您复制存储库中的部分或全部提交。它首先列出要复制的所有提交。然后,对于每个这样的提交,它:

  • 提取提交文件
  • 应用你的过滤器;及
  • 根据筛选结果进行新提交
  • 最后,过滤完所有提交后,它会使过滤后的分支名称(以及可选的带注释的标记)指向新的commmit,而不是旧的提交(仍在存储库中)

    如果过滤所有分支上的所有提交(以及使用
    --tag name filter cat
    过滤的所有标记名),则丢弃原始分支,结果是一个新的存储库,其中包含过滤器所做的任何更改。通常可以使用
    git filter branch
    删除某些敏感文件的所有副本(例如,使用密码)。也就是说,过滤器显示“如果文件dontcommit.txt存在,请将其删除”

    如果编写一个过滤器,上面写着“删除除file keep.txt以外的所有内容”,并使用该过滤器过滤所有分支中的所有提交和所有标记名,则复制的提交将只有一个文件。可以告诉筛选器分支放弃“空”提交,即那些在应用筛选器后未进行更改的提交,因此通过添加
    --prune empty
    ,可以丢弃影响其他文件的所有提交

    假设您有一个类似Unix的系统,它有一个好的
    find
    命令,那么这个过滤器分支应该可以完成这个任务。请注意,筛选器分支的提取速度非常慢,并且在大型存储库中重新进行所有提交需要大量的工作,应该在存储库的新克隆上完成(这样您就不会损坏原始克隆)

    当然,将
    path/to/keep.txt
    替换为您想要保留的文件。(请注意,这取决于Git不保存空目录的事实:
    rm-f
    将悄悄地在目录上失败,但将删除它们的所有内容,当然我们确保不打印的“保留”路径除外。)

    (另一种选择是将其复制到一边,然后删除所有内容, 然后将其移回原位:

    cp path/to/keep.txt /tmp/keep.txt &&
      rm -rf .??* * &&
      mv /tmp/keep.txt .
    

    它允许您更改文件在临时目录中的位置,
    git filter branch
    使用该临时目录进行每次新的提交。此处的
    ?*
    用于删除文件,如
    .gitignore
    .gittributes
    :工作树顶部的任何点文件。请注意,过滤是在tem中完成的不包含
    .git
    存储库本身的临时目录。)

    我尝试了您的第一个解决方案,但查找说明
    find:unknown predicate'-keep.txt'
    似乎有问题。我没能纠正它。您的第二个解决方案似乎没有保留文件夹,因此,如果在git筛选器分支之外执行cp,并且如果执行而不是查找,则具有提交历史记录的.git将丢失。。。然后
    没有这样的文件或目录树过滤器失败
    我将find命令改为:
    find-路径-o-path keep.txt-o-print0
    ,但是由于历史记录中的一些其他问题,我忽略了“重复的父项”,并且
    无法删除。“/C”:是一个目录
    ,将
    rm-f
    设置为
    rm-rf
    将删除所有内容,包括感兴趣的文件在我建议的树过滤器中没有
    -保留
    。。。你在这里的第二个评论看起来像我第一次提议的
    find
    :-)注意,其中的
    rm
    rm-f
    ,它应该以静默方式传递目录。如果您的rm由于某种原因出错,您可以添加
    -o-type d
    以跳过
    -print0
    之前的目录,或者如果您没有符号链接,则将其设置为
    -type f-print0
    cp path/to/keep.txt /tmp/keep.txt &&
      rm -rf .??* * &&
      mv /tmp/keep.txt .