如何告诉Git它是同一个目录,只是一个不同的名称


How to tell Git that it's the same directory, just a different name

在克服了学习git的一些障碍之后,我遇到了一个新的挑战:重命名一个目录(本地,在工作目录中)。

当我键入git status时,它会列出已删除的旧目录名(与新目录中的文件名完全相同)中的所有文件,新目录名为"未跟踪"。

有没有办法告诉Git"它实际上是同一个目录,只是一个不同的名称"?

所有文件都将由git status列出,仅作修改?

为了举例说明这个问题,当我重命名整个目录时,这里是从git status收到的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
git status
# On branch master
# Changes not staged for commit:
#   (use"git add/rm <file>..." to update what will be committed)
#   (use"git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    old-dir-name/file1
#   deleted:    old-dir-name/file2
#   deleted:    old-dir-name/file3
#
# Untracked files:
#   (use"git add <file>..." to include in what will be committed)
#
#   new-dir-name/
no changes added to commit (use"git add" and/or"git commit -a")
~/sb/ws>


只有git add这个目录的新名称。Git没有明确跟踪重命名,只是稍后检测到它们。git mv的执行效率可能稍高(因为它可以直接更新索引),但效果完全相同。


这里的所有答案对于我所面对的特定场景的实际解决方案都非常有帮助。我以实际步骤的形式为我提供了有用的东西,希望能帮助其他人迎接同样的挑战:

  • 埃多克斯1〔6〕
  • git status(核实所有文件标记为已重命名,而不是"已删除")。
  • 埃多克斯1〔8〕(这是"伪造"的承诺,准备对于下一个真正的重命名步骤)
  • 埃多克斯1〔9〕带时间戳的("假"分支)提醒我们这样做只是为了解决方法)
  • 埃多克斯1〔10〕
  • cp -Rp .../ .(副本在实际文件夹上重命名的名称)
  • git status(修改最多的文件现在将正确标记为已修改,未"删除"。已重命名的文件将标记为删除和添加,尽管内容相同!--如果这些文件也需要重命名跟踪,则对它们重复步骤1-7)
  • 埃多克斯1〔13〕
  • 埃多克斯1〔14〕
  • 江户十一〔15〕号:)
  • P.S.gitk喜欢这个,但是Emacs仍然与Renames混淆。:(


    您需要使用git的mv:http://www.kernel.org/pub/software/scm/git/docs/git-mv.html

    1
    git mv old_dir new_dir

    因此,您需要将新目录移回旧目录,然后用mv重新移动它。

    编辑:要回答我的回答:

    我决定亲自测试一下。我创建了两个文本不同的文件,其中一个使用git mv,另一个使用mv file file2git add file2git add -u。提交消息表明两者都被跟踪为重命名。因此,正如其他人所说,我的所有建议都是省去一步。


    Git 2.18(2018年第2季度)应该检测"它是同一个目录,只是一个不同的名称",因为"git status学会了关注与UI相关的不同配置变量,如diff.renames

    见Eckhard S.Maa提交的DC6B1D9(2018年5月4日)?(`)(由Junio C Hamano--gitster于2018年5月23日提交1E174fd合并)

    wt-status: use settings from git_diff_ui_config

    If you do something like:

    1
    2
    3
    4
    - git add .
    - git status
    - git commit
    - git show (or git diff HEAD)

    one would expect to have analogous output from git status and git show (or similar diff-related programs).
    This is generally not the case, as git status has hard coded values for diff related options.

    With this commit the hard coded settings are dropped from the status
    command in favour for values provided by git_diff_ui_config.

    What follows are some remarks on the concrete options which were hard
    coded in git status:

    1
    `diffopt.detect_rename`

    Since the very beginning of git status in a3e870f ("Add"commit"
    helper script", 2005-05-30, Git v0.99), git status always used rename detection,
    whereas with commands like show and log one had to activate it with a
    command line option.
    After 5404c11 ("diff: activate diff.renames by
    default", 2016-02-25, Git v2.9.0) the default behaves the same by coincidence, but changing diff.renames to other values can break the consistency between
    git status and other commands again.
    With this commit one control the same default behaviour with diff.renames.

    1
    `diffopt.rename_limit`

    Similarly one has the option diff.renamelimit to adjust this limit for
    all commands but git status. With this commit git status will also honor
    those.

    同样的Git2.18也提供了status.renames,这对于那些希望这样做而不禁用默认重命名检测的人来说是有用的。"git diff命令。

    见Ben Peart(benpeart)的Commit E8B2DC2(2018年5月11日)。(由Junio C Hamano--gitster于2018年5月30日提交5DA4847合并)

    add status config and command line options for rename detection

    After performing a merge that has conflicts git status will, by default,
    attempt to detect renames which causes many objects to be examined.
    In a virtualized repo, those objects do not exist locally so the rename logic
    triggers them to be fetched from the server. This results in the status call
    taking hours to complete on very large repos vs seconds with this patch.

    Add a new config status.renames setting to enable turning off rename
    detection during status and commit.
    This setting will default to the value of diff.renames.

    Add a new config status.renamelimit setting to to enable bounding the time
    spent finding out inexact renames during status and commit.
    This setting will default to the value of diff.renamelimit.

    Add --no-renames command line option to status that enables overriding the
    config setting from the command line.
    Add --find-renames[=] command line option to status that enables detecting renames and optionally setting the similarity index.


    问题是用户界面/用户体验问题,而不是Git的"实际"问题。我问过同样的问题,如何在Git中使用子目录重命名,以及一个底层问题,Git如何记录或更可能表示其blob的文件路径和名称?

    实际上Git并不在乎。你(我们)得到的所有信息都是关于"diff"认为可能发生的事情。使用其他选项,消息将是不同的,但存储库不会有任何不同(它是相同的快照!).

    一种选择样式是用于diff的subtree选项(尽管它的目的不同),正如--patience一样。

    需要一个更好的UI/UX选项,它可以更容易地检测路径更改(基于树而不是Blob)。问题的一部分是莱纳斯论点中的微妙错误。他说得对,Git repo不应该显式存储重命名(pathchange),而是需要一个选项来允许正确的发现。