关于git:如何重写历史记录,以便除了我已移动的文件之外的所有文件都在子目录中?

How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?

我在git下有一个项目。有一天,我把所有项目文件从当前目录移到了项目下的foo/bar/。我用git mv做的。然后我又添加了一些文件,并对已经存在的文件做了一些更改。

因此,现在当我查看foo/bar/file.c的历史时,我只能看到在移动文件之后所做的更改。

我试图用各种方法来解决这个问题(使用子目录过滤器等的filter-branch),但没有任何帮助,所以我被安排在这里。如果你能给我任何帮助,我将不胜感激。谢谢!


要用移动的文件重写历史记录,请执行以下操作:

如果您希望项目的历史看起来像所有文件都在foo/bar目录中,那么您需要做一点手术。使用带有"树过滤器"的git filter-branch重写提交,以便在不存在foo/bar的任何地方创建该提交,并将所有文件移动到该提交:

1
2
3
4
5
git filter-branch --prune-empty --tree-filter '
if [ ! -e foo/bar ]; then
    mkdir -p foo/bar
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar
fi'

现在,历史记录将被记录,就好像所有文件都始终位于foo/bar中一样。

要查看移动文件的历史记录,请执行以下操作:

如果您只想查看在过去某个时间点被移动或重命名的文件的历史记录,那么只需使用--follow选项到git log

1
git log --follow foo/bar/file.c


总结一下我所做的工作。对我有用的命令是:

1
if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo""; fi

我在末尾添加的echo命令确保即使mv失败,整个命令也将继续运行。它没有移动foo/bar/foo的内容,但我可以接受。

多谢丹的塑造(!!!!)杰弗洛米帮忙。