[英]How can I move a directory in a Git repo for all commits?
Let's say I have a repo that includes this directory structure:假设我有一个包含此目录结构的存储库:
repo/
blog/
_posts/
some-post.html
another-file.txt
I want to move _posts
to the top level of the repo, so the structure will look like this:我想将
_posts
移动到 repo 的顶层,因此结构将如下所示:
repo/
_posts/
some-post.html
another-file.txt
This is simple enough with git mv
, but I want to make the history look as though _posts
always existed at the root of the repo, and I want to be able to get the entire history of some-post.html
via git log -- _posts/some-post.html
.使用
git mv
这很简单,但我想让历史看起来好像_posts
始终存在于回购的根目录,我希望能够通过git log -- _posts/some-post.html
获得some-post.html
的全部历史记录git log -- _posts/some-post.html
。 I imagine I can use some magic with git filter-branch
to accomplish this, but I haven't figured out exactly how to do that.我想我可以使用
git filter-branch
来实现这一点,但我还没有弄清楚如何做到这一点。 Any ideas?有任何想法吗?
You can use the subdirectory filter to achieve this您可以使用子目录过滤器来实现这一点
$ git filter-branch --subdirectory-filter blog/ -- --all
EDIT 1: If you don't want to effectively make _posts
the root, use a tree-filter instead:编辑 1:如果您不想有效地使
_posts
成为根,请改用树过滤器:
$ git filter-branch --tree-filter 'mv blog/_posts .' HEAD
EDIT 2: If blog/_posts
did not exist in some of the commits, the above will fail.编辑 2:如果某些提交中不存在
blog/_posts
,则上述操作将失败。 Use this instead:改用这个:
$ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD
While Ramkumar's answer is very helpful and worthwile, it will not work in many situations.虽然 Ramkumar 的回答非常有用且有价值,但它在许多情况下都不起作用。 For example, when you want to move a directory with other subdirectories to a new location.
例如,当您要将包含其他子目录的目录移动到新位置时。
For this, the man page contains the perfect command:为此,手册页包含完美的命令:
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&NEWSUBDIR/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
Just replace NEWSUBDIR with your desired new directory.只需将 NEWSUBDIR 替换为您想要的新目录即可。 You can also use nested dirs like dir1/dir2/dir3/-"
您还可以使用嵌套目录,例如 dir1/dir2/dir3/-"
Created a generic script for arbitrary moves/renames: https://gist.github.com/xkr47/f766f4082112c086af63ef8d378c4304为任意移动/重命名创建了一个通用脚本: https ://gist.github.com/xkr47/f766f4082112c086af63ef8d378c4304
Examples:例子:
git filter-mv 's!^!subdir/!'
➜ moves all files to a subdirectory "subdir/" in all commits of the current branch ➜ 将所有文件移动到当前分支的所有提交中的子目录“subdir/”
git filter-mv 's!^foo/bar.txt$!foo/barbar.txt!'
➜ renames foo/bar.txt to foo/barbar.txt in all commits of the current branch ➜ 在当前分支的所有提交中将 foo/bar.txt 重命名为 foo/barbar.txt
git filter-branch
is discouraged.不鼓励 git
filter-branch
。 You can use git filter-repo
is much more convenient:你可以使用 git
filter-repo
方便得多:
git filter-repo --path-rename blog/_posts:_posts
Also note that installation somehow is broken , and you have to install from pip and add git-filter-repo
to $PATH
另请注意,安装以某种方式损坏,您必须从 pip 安装并将
git-filter-repo
添加到$PATH
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.