如何将代码重构为新文件并保留 git 历史记录?

2024-01-13

所以我想将一个大文件的一部分提取到一个新文件并保留 git 历史记录,这样我就可以运行git blame并查看重构之前的变化。


In Git, the history is the commits. There is no file history. This is unlike most other version control systems: Those other VCSes that do track "file identity" need you to inform them that new file path/to/new.ext is derived from path/to/existing.ext so that they can associate the new file's history with the old file's history. Similarly, they need you to inform them about file renames—although some, like ClearCase, can auto-detect renames by simply acting as the file system for the work-tree. Git does not need any of this because it does not work that way.1

Instead, in Git, when you compare one commit—call it a—to another (b), Git attempts to discover (dynamically, at compare-time) whether some file a/path/to/name is "the same" as another file b/some/other/path/to/anothername. The degree of comparison and the algorithm for deciding that these are the same file, or are different files, are up to the Git command. The git diff command starts by looking at the actual path names: if they are the same, the files are the same,2 otherwise they are probably different. The "probably" part is where rename detection comes in, if you have enabled it. A regular git diff also has -C and --find-copies-harder to enable "file-copied-from" detection. Using -C twice (or --find-copies-harder) sets things up to look for new files being copied from any file in the a commit (this is considered too expensive to do automatically; normally, only files that are otherwise considered "modified" are treated as source-of-copy candidates).

The git blame命令有些不同(并且a and b提交只是每个提交的自动父子),但它仍然有一个-C选项。它是-C工作方式有点不同:一个-C寻找lines从提交之间修改的文件复制a and b。使用-C两次查找复制自的此类行any提交中的文件a,并与三个-C标志,它将“更难找到副本”:它将查看中的每个文件every提交查找复制的代码。

Hence, for most purposes you can just use one -C on your git blame. You should use -C -C if the copied code comes from a non-modified file. Use three -Cs if you believe some code was deleted many revs ago, then resurrected, and you want to find the original source. Note that git blame's -C option turns on git blame's -M option, which detects moved code (and is therefore quite different from git diff's -M option—file rename detection, a la git log --follow,3 is always enabled).


1This is a nice advantage for Git over other VCSes, because Git can detect cases that humans forgot, and also can detect renames when comparing "far apart" revisions. It's a terrible disadvantage for Git, because it must detect cases even if humans would not have forgotten, and hence misses renames. It's a big advantage for Git, because future smarter algorithms use the existing data in better ways. In short, there are arguments for why it's better and why it's worse, but ultimately it's just different.

2For git diff, you can conditionally break apart these automatically-paired "same name means same file" pairings using its -B option. This is unavailable to, yet unnecessary for, git blame, which is not doing this kind of pairing.

3The code enabled by --follow in git log is a horrible hack that basically only works for the one case required by git blame. Do not try to use --follow with reverse-order git log.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将代码重构为新文件并保留 git 历史记录? 的相关文章

  • 使用两个帐户推送到 Git

    我跟着这个tuotrial http code tutsplus com tutorials how to work with github and multiple accounts net 22574关于如何在同一台计算机上拥有两个单独
  • git 分叉是如何工作的?

    所以我登录了 github 并 fork 了一个项目 每次原始存储库更新时 我的分叉存储库都会更新吗 或者我应该每次都从原始存储库进行分叉 这样我就不会错过对原始存储库所做的任何新更改 分叉是存储库的副本 分叉存储库允许您自由地尝试更改 而
  • `git add --patch` 和 `--word-diff`

    git add patch提供了一个很好的界面 用于检查未暂存的更改 然后仅暂存下一次提交中需要的更改 很好 除了一件事 没有明显的方法来选择哪个diff视图来使用 特别是 我希望能够配置git add patch以同样的方式向我呈现差异g
  • 您对版本控制进行到什么程度了? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 签出现有的远程分支

    我见过不同的方法来检查现有的远程分支 假设我的朋友推送了新分支 bigbug 并且我想签出并将我的本地工作副本切换到该分支 我有以下选项 1 git checkout b bigbug origin bigbug 2 git checkou
  • 我可以从命令行向 github 添加问题吗?

    我是 git 新手 我希望能够通过 github 绘制我的项目的计划和进度 问题是 这需要在 github com 上使用浏览器进行大量点击 并且我希望能够通过使用命令行程序来自动执行该任务 github 有命令行界面吗 有一个ghi ge
  • “git rm --cached”、“git Restore --staged”和“git reset”之间有什么区别

    我遇到了以下三种方法来取消暂存由命令 git add 暂存的文件 git rm cached
  • 如何避免开发人员将凭证推送到 bitbucket?

    我们有一个应用程序 它使用 JSON 文件来定义数据库和其他 API 的连接字符串和凭据 理想情况下 这些凭证作为变量添加到 bitbucket 存储库中 并在 Jenkins 的构建期间进行替换 开发商在当地与他们合作时更换了他们 我们需
  • 有关多个远程存储库的 Git 状态

    我有一个脚本 如果我忘记在 40 多个存储库中提交或推送一些代码 它会通过电子邮件向我发送提醒 在我的两个项目中 我遵循了这些帖子中的答案 其中我设置了 git push 来推送到多个存储库 从多个远程位置拉 推 https stackov
  • 如何让 git 和 copSSH 在正确的目录中查找密钥?

    我刚刚安装了 Windows 版 copSSH 当我启动它时 我得到一个目录C copSSH home Nick ssh其中有我的酒吧和私钥 当我通过 Cygwin bash 窗口访问此目录时 使用 ssh 用户 主机 我很高兴地登录了 但
  • @VisibleForTesting 的替代方案

    我知道 VisibleForTesting 是不可取的 因为它只是为了测试目的而更改类的接口 理想情况下 我们应该测试我们实际使用的接口 但什么是一个好的替代方案呢 You use VisibleForTesting正如您所说 当您想要测试
  • 由于不存在大文件而导致 git Push 错误

    当尝试推送到 git 时 我不断得到相同的结果 Counting objects 78 done Delta compression using up to 4 threads Compressing objects 100 67 67 d
  • 如何标记单个文件?或如何下载特定文件? - 胃肠道

    我想向文件添加标签以轻松下载该文件而不是整个分支 如何下载GIT中的特定文件 我不知道有什么方法可以标记特定文件git 对于第二个问题 如何下载特定文件git 仅当您的意思是 同时下载 时 以下内容才有效in a git存储库 这就是我理解
  • 如何使用 sourceTree 进行推送?

    我正在使用 sourceTree 管理 Unity 项目 版本 4 6 3 我只是想返回到上一次提交 右键选择 将当前分支重置到此提交 在使用模式中选择 硬 然后放回上一次提交 之后 我尝试去推 但没有成功 抱歉 当时我忘记了错误 之后 我
  • 通过链接进入 git-repo,无需冗长的对话框

    In a directory I have symbolic links into a git administered directory all under Linux Every time I want to e dit such a
  • RuntimeError:模型类 django_messages.models.Message 未声明显式 app_label 并且不在 INSTALLED_APPS 中的应用程序中

    我正在尝试使用https github com arneb django messages https github com arneb django messages打包我的消息传递内容并尝试了以下操作 pip install git h
  • Eclipse 与外部 src 和 Web 内容文件夹链接或映射

    首先这不是问题但是我遇到的问题的解决方案浪费了4 5个小时来找到解决方案 请让我知道是否有更好的替代方法来使用 eclipse 项目管理外部 src 文件夹 我正在使用版本控制系统 GIT 来管理我的项目 还使用外部 Git 客户端 Sou
  • gitlab 上的权限被拒绝(公钥)

    我的问题是我无法从 GitLab 推送或获取 不过 我可以克隆 通过 HTTP 或通过 SSH 当我尝试推送时出现此错误 权限被拒绝 公钥 致命 无法从远程存储库读取 从我看过的所有线程中 这是我所做的 在我的计算机上设置 SSH 密钥并将
  • 如何解决 VS Code 中变基拉取的合并冲突?

    当我做一个git pull rebase 并且我的提交中存在合并冲突 我得到冲突差异视图 解决所有冲突并暂存文件 然后呢 我可以打开终端并运行git rebase continue但是 VS Code 中不应该有一个按钮来完成变基吗 只需使
  • 在centos上设置jenkins:ssh密钥和git的问题

    经历了很多问题 但似乎没有什么能解决我的问题 或者更准确地说 我不确定我是否正确地完成了整个事情 所以这里是 已安装centos 6 3操作系统 然后我按照以下指南安装詹金斯 https wiki jenkins ci org displa

随机推荐