1

我正在尝试导出两个提交之间存在差异的所有文件,这些差异是:

  • 新文件(添加)
  • 修改文件
  • 重命名文件
  • 如果可能,有关任何已删除文件的信息

检测重命名可能是一项艰巨的任务,因为我将在Windows 7环境中进行导出,因此somefile.phpSomeFile.php; 但我会将它们上传到*nix环境,该环境确实将这些文件视为不同的,因此如果可能,需要识别和导出它们。

我正在使用以下命令:

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $head_commit_id $older_commit_id | xargs tar -cf project.tar -T -

但是我注意到它没有导出新/添加的文件,也没有导出重命名的文件;然后我发现git diff-tree默认情况下不进行重命名检测,所以从我所看到的我需要添加--find-renames到命令中?

4

2 回答 2

2

为什么不使用这个简单的状态命令:

git diff --name-only SHA1 SHA2
# or

# --name-status will display the name and the status of the files
git diff --name-status SHA1 SHA2

# To display untracked files use the -u
git status -u

在 git 中,您应该只使用git mv 命令重命名文件。

于 2017-02-25T15:55:04.063 回答
2

正如在CodeWizard 的回答中一样,您可以使用“用户友好”(或瓷器)命令git diff而不是git diff-treeGit 所谓的管道命令,用于脚本中。但是,您应该知道这意味着什么。

由于瓷器命令是为人类设计的,它们试图以人类可读的方式呈现事物。这意味着他们遵守特定人在各种配置文件中为他/她自己设置的任何设置。这包括diff.renamesdiff.renameLimit配置。他们也可能会修改他们的输出,使眼球更容易处理,但计算机程序更难处理。最糟糕的是,如果人们似乎更喜欢某些默认值,他们可能会将输出从一个 Git 版本更改为另一个版本。

由于脚本不适用于上述情况,它们以可预测的方式运行,输出不会改变,也不依赖于配置项。这样,无论您提出什么要求,您都会得到:您将以可靠的形式获得可靠的输出,因此,如果您编写自己的可靠代码,它不仅适用于今天,在一种情况下;在所有可能的情况下,它将在未来继续工作。1

最后,这意味着如果您使用git diff-tree并设置正确的标志,您将获得更可靠的输出。如果您使用git diff,您的重命名检测取决于:

正如您所发现的,rename-detection 的输出是两个路径名,这不是您可以通过管道传输到存档器的内容。存档者通常会遇到文件删除问题(这可能是存档备份/快照之间的一个典型区别;请注意,这两者都与版本控制有关)。

如果您的目标是所有文件的一种联合 - 即,如果差异表明A添加了一个名为的D文件,删除了一个名为的文件,并且R通过重命名旧名称来创建文件O(并且可能还修改它:注意 Git 的相似性索引字母后面的数字R),那么您希望收集文件A,忽略文件D,并R在忽略文件的同时收集文件O- 那么,您想要的是首先检测重命名!如果您检测到重命名git diff-tree(默认情况下不会检测到),则相同的差异将显示为:添加文件A、删除文件D、删除文件O和添加文件R. 因此,包含和排除git diff-tree的 a就足够了。不太清楚如何处理类型更改:例如,从普通文件到符号链接,或者从文件到子存储库提交哈希(Git 称之为gitlink条目,用于子模块)。diff-filterAMDT

同样,您不想启用复制检测:C状态,如R,表示相似性索引和一路径名。如果您将其禁用,您只需将新路径名作为Added 文件获取。

即使你做了所有这些,你仍然会陷入陷阱。假设提交哈希C1有一个名为 的文件problem,而(可能是稍后的)提交哈希C2有两个名为problem/A和的文件problem/B。这意味着在这两点之间删除了原始文件,因为大多数系统(包括 Git 本身)都禁止同时拥有一个problem名为文件和一个名为problem目录来保存各种problem文件。鉴于每个 tar-archive 本身不是一个完整的快照——你忽略了C1C2之间未修改的文件——你的解压过程这些快照必须是附加的:提取较早的快照,然后在较早的快照之上提取较晚的快照。此过程将在文件处于创建目录的方式时失败。显然,您可以检查此类问题并删除有问题的文件(您现在可以看到我为什么将文件命名为:-)),但更一般地说,由于您首先没有存储“删除”指令,因此您不会知道,在将来您使用这些档案来重建快照的情况下,某些文件根本不属于该快照。problemproblemproblem

(这个问题的经典解决方案是在 update-archives 前面加上某种清单或指令。如果您决定使用这样的解决方案,那么,根据清单或指令中所需的详细信息类型,您可能想要进行第一次检查以检测准确的重命名和/或准确的副本。)


1显然,新添加的功能会给每个人带来问题,不仅仅是脚本,也不仅仅是人类,但 Git 人员确实努力不给依赖管道命令的脚本带来不必要的问题。例如,考虑一下推动 Git 使用某种 SHA-256 替代或补充 SHA-1 的新动力。由于 SHA-1 产生 160 位散列,而 SHA-256 产生 256 位散列,因此它们必须分别表示为 40 位和 64 位十六进制数字。Linus 建议默认将 256 位哈希缩写为 40 个字符,以帮助现有的假设40 个字符的脚本,但我预见到一些问题...... :-)

于 2017-02-25T18:36:54.583 回答