【问题标题】:How to find the new path of a renamed file whose original name is known?如何找到原始名称已知的重命名文件的新路径?
【发布时间】:2012-04-28 20:31:01
【问题描述】:

考虑以下用例:

我正在本地分支上工作,而主分支上已经完成了重构。现在一些文件(类)已被重命名和/或移动到新位置。合并时,由于缺少类,我会遇到很多导入错误。

--A--B--C--D--E-- (master)
   \           \
    F--G--H--I--J  (topic)

A 中有我在F--G--H--I 中使用的旧名称。

B--C--D--E 中,文件被重构,导致E 中的新文件名。这包括链式重命名,如

   B: path/to/File.java              
-> C: path/to/BetterName.java
-> D: better/package/BetterName.java 
-> E: final/package/FinalName.java

由于我的分支上缺少重构,现在合并导致J 出现许多(编译)错误。 (因为我还是指path.to.File而不是final.package.FinalName

为了修复损坏的构建,我需要知道旧类的新名称。

是否有 git 命令来获取已应用于特定文件的所有重命名?

【问题讨论】:

  • 你的脚本有效吗?如果是,我不明白你的问题
  • 是的,它可以工作,但我想知道是否有比上面的脚本更简单的解决方案。因为我必须对每个文件都这样做。
  • 您需要告诉git log 使用-M 选项查找重命名。然后,您只想报告重命名,这可以通过 --diff-filter 选项完成。我在回答中添加了更多细节。
  • 我认为重要的是要注意,一个特定的文件在不同的提交中被多次重命名

标签: git refactoring git-bash


【解决方案1】:

Git 应该找到文件的重命名。但是,如果该文件在该文件中有 50% 或更多的行更改,则不再将其视为重命名。您可以根据需要更改此阈值。

这是执行此操作的命令:

git log -M --diff-filter=R --stat

它只会显示重命名。如果您想将阈值更改为默认 50% 以外的其他值,只需将数字添加到 M 选项:

git log -M90 --diff-filter=R --stat

仅当文件内容更改不超过 10% 时才会认为文件已重命名

更新:

要跳过所有中间步骤,请改用 diff。 Git 会为你重命名:

git diff -M --diff-filter=R --name-status ..master | cut -f2-

当你在你的主题分支上时。

然后,您可以通过管道生成一堆 sed 指令来调整您的引用。

【讨论】:

  • 你的命令很有用,但我仍然需要抓取它才能实现我的目标
  • 你想要什么?您可以根据自己的喜好格式化输出。如果需要,您应该能够将它传递给更多命令。你不应该回顾你的历史。
  • git log -M --diff-filter=R --name-status --reverse 按所需顺序提供所有重命名的列表(最早的在前)。但我只有旧名字。问题不在于找到旧名称的直接重命名,而是在之后找到所有连续的重命名。希望它现在可以理解了。
  • 然后让 git 用 diff 汇总所有重命名。更新了我的答案。
  • git log --diff-filter=RD --summary --reverse 最适合我
【解决方案2】:

我在网上找不到令人满意的答案,所以我写了一个(尴尬的)脚本来逐一检查日志(通过重命名来重命名)

使用上面示例的脚本提供以下输出:

$ git history path/to/File.java

final/package/FinalName.java

我将脚本添加到我的 ~.bashrc 并将选项 alias.history=!bash -ic 'git_file_history "$@"' - 添加到我的全局 git 配置

#! /bin/sh
### Takes a filename as parameter ($1)
### Echoes all filenames related to $1
function git_file_history() {
        loc_var=$1;
        old=""
        while [ "$loc_var" != "$old"  ] && [ "$loc_var" != "" ]
        do
                old=$loc_var;
                #echo $loc_var;
                hashes=$(git log --format="%P %H" -1 --follow --  $loc_var);
                status=$(git diff --name-status --find-renames $hashes | grep $loc_var);
                awks=`echo $status | awk '{print $3}'`
                loc_var=$awks;
        done 
        echo "$loc_var";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多