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

Ale*_*ler 54 git history mv git-filter-branch

我有一个项目git.有一天,我将所有项目文件从当前目录移动到foo/bar/项目下.我是用它做的git mv.然后我添加了一些文件并对现有文件进行了一些更改.

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

我尝试以各种方式解决这个问题(filter-branch使用子目录过滤器等),但没有任何帮助,所以我在这里很好.我很感激你能给我的任何帮助.谢谢!

Dan*_*ing 94

要使用移动的文件重写历史记录:

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

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'
Run Code Online (Sandbox Code Playgroud)

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

要查看已移动文件的历史记录:

如果您只想查看过去某个时刻已移动或重命名的文件的历史记录,则只需使用以下--follow选项git log:

git log --follow foo/bar/file.c
Run Code Online (Sandbox Code Playgroud)

  • 使用`[[`给我带来了一个问题,因为没有这样的命令(它是一个shell bulitin),使用`[`和`]`解决了这个问题. (6认同)

Ale*_*ler 7

在这里总结一下我对我所做的一个简短的总结.对我有用的命令是:

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
Run Code Online (Sandbox Code Playgroud)

我最后添加的echo命令确保即使mv失败,整个命令也会继续运行.它没有移动foo/bar/foo的内容,但我可以忍受.

非常感谢Dan Molding(!!!)和Jefromi的帮助.