Git仓库中为所有提交重命名文件

23

我想重命名一个Git仓库中所有提交的文件。这是我尝试过的:

git filter-branch --index-filter 'git mv -k <old name> <new name>' HEAD

这个命令遍历了存储库中的所有提交,但最终出现以下消息:

警告:Ref 'refs/heads/master' 未更改

这意味着没有进行任何更改。问题出在哪里?

请注意,我想要重命名的文件在第一个提交中并不存在。因此,如果我在 git mv 命令中不使用 -k,也就是说,如果我使用:

git filter-branch --index-filter 'git mv <old name> <new name>' HEAD`

尝试第一次提交时,Git可能会出现错误,显示“坏源...”等信息。


你将用它改变历史。 - three
4
是的,这就是filter-branch的目的。 - Rodney Folz
1
我知道“filter-branch”就是关于重写历史的,这正是我想要的。 - York
你可以尝试使用 --tree-filter 吗?我知道它比仅索引慢,但如果它能正常工作... - knittl
是的,我确实尝试了“tree-filter”,就像这样:$ git filter-branch --tree-filter 'mv <old name> <new name>' HEAD问题在于,我想重命名的文件在第一个提交中并不存在,因此git会抛出“mv: cannot stat <old name>': No such file or director”错误。在“mv”命令之前,我该如何测试文件是否存在? - York
3个回答

21

最终我通过使用以下方法解决了我的原问题:

git filter-branch --tree-filter '
if [ -f <old name> ]; then
  mv <old name> <new name>
fi' --force HEAD

5
对于使用 --index-filter 的解决方案,请参考这个答案 - Daniel Hilgarth
3
请注意,“git mv”不能与索引过滤器一起使用,因为“git mv”需要一个工作副本,而只有使用树过滤器才能获得工作副本。 - user456814
4
if [ -f <old name> ]替换为if [ -d <old name> ],以重命名目录而不是文件。 - naitsirhc

7

如果你的 Git 版本足够新的话,git-filter-repo 很棒。 - York
为什么你要使用旧版的Git?2.22版本已经过时2年了。 - Benjamin Goodacre
我总是使用最新的git(在archlinux上),但仍有一些人没有选择,被困在旧版本的git上。 - York

0

对于任何只想重命名文件的人来说,git rebase -i 就足够了。在 rebase 中包含创建该文件的提交,用 edit 标记它,然后重命名文件即可。Git 将正确地将下一个提交应用于此文件。


1
这个方案是可行的,但需要你手动为每一次提交重命名文件。如果只有一次提交也不成问题,但使用filter-branch可以在一个步骤中清理整个分支。 - STW
1
当我在@STW尝试时,我只需要在创建文件的提交中重命名文件,Git聪明到足以在之后应用重命名文件的修改,这真的让我感到惊讶(以一种好的方式)。 - Mr_and_Mrs_D
没错,如果你只需要回到一个或两个提交,这是一种更快、更安全的方法。明智地选择你的工具吧!对了,Git 真是太棒了。 - STW
这将从您的HEAD提交创建一个新的提交,其中文件已重命名,但如果您查看历史记录,您会发现该文件仍具有旧名称,即使您在具有相同文件的另一个分支上进行rebase也无济于事。 - Mihai Soloi
即使您将已重命名的文件与新提交一起包含在内,也是如此。@MihaiSoloi - Mr_and_Mrs_D

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