在Git提交历史中重命名目录

4

我试图重命名一个目录,这个目录在六次提交之前被引入,并在所有后续提交中使用。这些提交尚未推送。

我尝试了什么?

  • 我尝试使用带有mv old new命令的git filter-branch,但这会在HEAD~6之前的提交上失败,因为该目录不存在。
  • 我尝试使用git rebase -i HEAD~6,编辑每个提交,但我无法使用mv old new,因为git锁定了该文件,也不能在Windows Explorer中重命名它。
  • 我尝试使用cp -R old new; rm -rf old; git add new进行相同的变基,但这会在HEAD~4及以上产生合并冲突。

值得注意的是,引入该目录的提交是此分支中的第一次提交(该分支领先于master六次提交),而且自从我分支出来以后就没有碰过master

我还阅读了this question

什么是最好的方法来做这件事?


为什么不直接在主分支上创建一个新的分支,然后在 ~N 处简单地交换旧分支和新分支,并挑选出连续的 6 次提交(例如 cherry-pick & git mv old new & commit)?这可能不是“快速”的,但它会相当迅速。 - Philip Oakley
@PhilipOakley 好建议!我以前没用过 cherry-pick,但它很有效。如果你把它作为答案发布,我会接受的。 - wchargin
3个回答

4

git filter-branch 应该能正常工作;只需要通过追加 || truemv 命令具有优雅失败的能力。例如,将 baz/ 重命名为 foo/bar/baz/:

git filter-branch --force --tree-filter \
    'mkdir -p foo/bar; mv baz foo/bar/ || true' \
    --tag-name-filter cat -- --all

2

https://git-scm.com/docs/git-filter-branch说明:

将整个树移动到子目录中,或从子目录中删除它:

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

谢谢你的回答。你能解释一下它是如何工作的吗?特别是,GIT_INDEX_FILE环境变量有什么用?(我知道替换管道是做什么的,但不知道目标是什么。) - wchargin
我不确定,正在尝试找出细节...现在只是复制粘贴示例。而且它确实有效。 - Max

0
为什么不直接在主分支上创建一个新的分支,然后在 N 处简单地切换旧分支和新分支,并将 6 个提交拾起。
例如:git cherry-pick & git mv old new & git commit。
虽然可能不是很快,但只需要修复 6 个提交很快就能完成。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接