如何在保留历史记录的同时将文件从一个 git 存储库移动到另一个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10524578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 06:53:40  来源:igfitidea点击:

How to move a file from one git repository to another while preserving history

gitgit-filter-branch

提问by Randall Cook

I am trying to move a single file (call it foo.txt) from one repository to another (unrelated) repository, preserving its history. ebneter's questionshows how to do this for a subdirectory. taw's questionhas some hints and suggestions, but not a step-by-step procedure to follow. jkeating's questionlooked promising, but didn't work for me. Google searches came up empty for this particular use case. What I am looking for is a clear sequence of commands to accomplish this.

我试图将单个文件(称为 foo.txt)从一个存储库移动到另一个(不相关的)存储库,以保留其历史记录。ebneter 的问题显示了如何为子目录执行此操作。taw 的问题有一些提示和建议,但不是要遵循的分步程序。jkeating 的问题看起来很有希望,但对我不起作用。对于此特定用例,Google 搜索结果为空。我正在寻找的是完成此操作的清晰命令序列。

The sequence of commands I started to follow was this:

我开始遵循的命令序列是这样的:

$ git clone source-repo/ source-repo-copy
$ cd source-repo-copy
$ git filter-branch --tree-filter 'test ! "$@" = "foo.txt" && \
  git rm --cached --ignore-unmatch $@ || true' --prune-empty

The logic of my filter command is to git rmall files that are not foo.txt. I added the || trueto the command to force it to have a zero return value to satisfy filter-branch.

我的过滤器命令的逻辑是git rm所有不是 foo.txt 的文件。我|| true在命令中添加了以强制它具有零返回值以满足过滤器分支。

My intention was to set source-repo-copy as a remote for my target repository (target-repo), and assuming git filter-branchfiltered out everything but foo.txt, fetch and merge source-repo-copy into target-repo. Unfortunately, the git filter-branchcommand seemed to have no effect. It ran with no errors and appeared to grind through the 600+ commits in source-repo, but when it finished, the git logand files in source-repo-copy looked the same. Shouldn't all files but foo.txt be missing and all commits that didn't touch it be gone from the log?

我的意图是将 source-repo-copy 设置为我的目标存储库 (target-repo) 的远程副本,并假设git filter-branch过滤掉除 foo.txt 之外的所有内容,然后将 source-repo-copy 提取并合并到 target-repo 中。不幸的是,该git filter-branch命令似乎没有效果。它运行时没有错误,并且似乎在源代码库中的 600 多个提交中进行了打磨,但是当它完成时,git log源代码库副本中的和 文件看起来相同。难道除了 foo.txt 之外的所有文件都应该丢失,并且所有未触及它的提交都应该从日志中消失吗?

At this point I don't know how to proceed. Any suggestions?

在这一点上我不知道如何继续。有什么建议?

采纳答案by blang

This worked for me, but with a whole directory.

这对我有用,但有一个完整的目录。

As shown here

如图所示这里

~$ cd neu
~/neu$ git filter-branch --subdirectory-filter FooBar HEAD
~/neu$ git reset --hard
~/neu$ git remote rm origin
~/neu$ rm -r .git/refs/original/
~/neu$ git reflog expire --expire=now --all
~/neu$ git gc --aggressive
~/neu$ git prune
~/neu$ git remote add origin git://github.com/FooBar/neu.git

EDIT: For a single file:

编辑:对于单个文件:

Filter the directory first:

先过滤目录:

 git filter-branch --prune-empty --subdirectory-filter myDirectory -- --all

Filter the single file:

过滤单个文件:

 git filter-branch -f --prune-empty --index-filter "git rm --cached --ignore-unmatch $(git ls-files | grep -v 'keepthisfile.txt')"

Do some cleanup:

做一些清理:

 git reset --hard
 git gc --aggressive
 git prune

This should do it.

这应该做。