如何从历史记录中删除删除和重命名?

How to remove deletions and renames from the history?

在git中,如何去除文件删除和重命名,从分支中的某个提交开始,同时维护每个文件的更改历史(删除和重命名)?

我的用例是我选择了一个分支并从那里开始了一个新分支,在该分支中我删除了一些文件并重命名了一些其他文件。然后我修改了剩余的(并且经常重命名的)文件(并且还添加了一些文件)。现在我想恢复到原始名称并恢复已删除的文件(仍然存在于公共基础上),同时保留所有内容的历史记录。我的最终目标是能够合并回原来的分支(所以without the renames and file deletions that I introduced)。

这能做到吗?我想知道这有多容易,特别是因为重命名的文件被修改了(所以天真地删除重命名会切断原始文件和修改之间的历史记录link,我反而想保留)…

PS:自分支分支以来的变化是广泛的(至少在 "cleaned" 分支上)。

您可以尝试在分支点对有问题的分支执行 git rebase -i。为了安全起见,我会先在你想要破坏的分支的顶端创建一个新分支,以防万一(哈!墨菲定律是无情的)出现问题。

如果更改非常广泛,有一些方法可以自动执行此操作,但这更不确定。详情见Pro git book

您无需重写历史即可使合并工作。您可以还原重命名并重新引入已删除的文件,然后提交并合并。使用 git mv 将文件重新命名。可以使用 git checkout <rev-which-deleted-the-file>^ -- <filename> 恢复已删除的文件。 See this answer for details.

可以使用 git-log--diff-filter.

找到已删除和重命名的文件

Git 不存储重命名,它使用一些启发式方法即时计算它们以处理小的编辑。 git-loggit-diffgit-blame 都有 -C-M 等选项来控制 Git 尝试查找复制和重命名(移动) 文件。所以历史的连续性不一定会因为分支的更名而丢失。


如果你真的想重写你的历史,首先找到所有使用git log --diff-filter=D master..branch删除文件的更改。然后您可以使用 git rebase -i 更改这些提交并恢复已删除的文件。

重写有点棘手,因为您必须撤消重命名,然后在每次后续提交中重命名文件。这是 git-filter-branch 的工作,它可以将相同的更改应用于一系列提交。

git filter-branch --tree-filter 'if [ -f new ]; mv new old; fi' master..branch

--tree-filter 在每次提交时运行 shell 命令,然后根据需要通过添加和删除文件来更改提交。

和以前一样,要找到您的重命名,请使用 git log --diff-filter=R master..branch