使用 HEAD 从 git diff 输出中获取添加和删除的文件

Get added and deleted files from git diff output with HEAD

我正在使用 git diff 来获取特定文件的提交和他的 parent 之间的差异。 我正在使用这个命令:

git diff parent-sha child-sha  -- file/to/path

这是我的问题:使用此命令我可以为特定提交添加、删除和修改文件。但是当我在当前提交上尝试它时,我只能获得 modified/deleted 个文件。我正在寻找一种方法来为当前提交删除和添加文件(与他的 parent 相比)。

例如,这是我未提交的更改:

如果我运行git diff HEAD -- yarn.lock

我明白了

diff --git a/yarn.lock b/yarn.lock
deleted file mode 100644
index c06acb9..0000000
--- a/yarn.lock
+++ /dev/null
@@ -1,10383 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"7zip-bin@~4.1.0":
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-4.1.0.tgz#33eff662a5c39c0c2061170cc003c5120743fff0"
-  integrity sha512-AsnBZN3a8/JcNt+KPkGGODaA4c7l3W5+WpeKgGSbstSLxqWtTXqd1ieJGBQ8IFCtRg8DmmKUcSkIkUc0A4p3YA==
-
-"@angular-devkit/architect@0.11.4":
-  version "0.11.4"
-  resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.11.4.tgz#f0cc3b4f1dd0128f6b41d3bb760bcf4c324cd063"
-  integrity sha512-2zi6S9tPlk52vyqN67IvFoeNgd0uxtrPlwl3TdvJ3wrH7sYGJnkQ+EzAE7cKUGWAV989BbNtx2YxhRDHnN21Fg==

但是 git diff -- src/app/models/DiffFileInformation.ts

上什么都没有

git diff HEAD -- path 将显示您的本地修改。

文件 src/app/models/DiffFileInformation.ts 未被跟踪和暂存,因此它不会出现在您的 diff 中。

要在 diff 中看到它,您需要先暂存(添加)它。

下面3个命令不一样:

git diff
git diff HEAD
git diff HEAD^ HEAD

假设我们已经初始化了一个 repo 并进行了两次提交和一些额外的未提交更改。

git init foo
cd foo
touch a.txt b.txt
git add .
git commit -m 'first commit'

echo hello >> a.txt
echo hello >> b.txt
git commit -m 'hello'

echo world >> a.txt
echo world >> b.txt
# stage a.txt and leave b.txt alone
git add a.txt
  1. git diffreturn是什么意思?

git diff 比较工作树和索引。工作树有a.txtb.txt的修改版本,索引只有a.txt的修改版本。所以区别在于工作树的 b.txt 和索引的 b.txt:

hello
world

VS

hello

git diff returns:

diff --git a/b.txt b/b.txt
index ce01362..94954ab 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
 hello
+world
  1. git diff HEADreturn是什么意思?

它将 HEAD 修订版中的文件与工作树中的文件进行比较。 HEAD 中的 a.txt

hello
工作树中的

a.txt

hello
world

b.txta.txt一样,所以git diff HEADreturns:

diff --git a/a.txt b/a.txt
index ce01362..94954ab 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1,2 @@
 hello
+world
diff --git a/b.txt b/b.txt
index ce01362..94954ab 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +1,2 @@
 hello
+world
  1. git diff HEAD^ HEADreturn是什么意思?

它将前一个版本的文件与后一个版本的文件进行比较。在HEAD^中,a.txtb.txt都是空的。在HEAD中,两者都是:

hello

所以我们得到 git diff HEAD^ HEAD 的输出为:

diff --git a/a.txt b/a.txt
index e69de29..ce01362 100644
--- a/a.txt
+++ b/a.txt
@@ -0,0 +1 @@
+hello
diff --git a/b.txt b/b.txt
index e69de29..ce01362 100644
--- a/b.txt
+++ b/b.txt
@@ -0,0 +1 @@
+hello

如果我们交换 HEAD^HEADgit diff HEAD HEAD^ returns:

diff --git a/a.txt b/a.txt
index ce01362..e69de29 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +0,0 @@
-hello
diff --git a/b.txt b/b.txt
index ce01362..e69de29 100644
--- a/b.txt
+++ b/b.txt
@@ -1 +0,0 @@
-hello

HEADHEAD^ 可以是存储库中可访问的任何提交。除了交换修订版,我们还可以使用选项 -Rgit diff -R HEAD^ HEAD.

获得反向差异

不确定您的确切目的是什么。也许你可以找到解决方案here。描述了 git diff 的更多语法。

是正确的(我已经赞成)但是如果你退后一步并考虑 commits 和Git 是如何工作的。

每个提交都包含几项内容,我们可以将其分为两大类,数据元数据。 commit中的data是源代码快照,metadata是数据的额外信息about ,例如谁制作了快照,什么时候等等(重要的是,此提交的父级的 父级哈希 ID,或者如果它是合并提交,则其所有父级哈希ID,但我认为你现在已经很好地控制了那部分)。请注意,提交中的所有内容都被永久冻结。您不能更改数据 或元数据 的任何部分。

事实上,Git的所有的内部对象都是如此。 Git 对象的哈希 ID 是该对象内容的加密校验和。这对归档非常有用——每次提交,一旦提交,永远不会被改变——但它对完成任何新工作完全没用。要进行新工作,Git必须提供一些可以修改.

文件的地方

每个版本控制系统都有这个问题,一般来说,它们都以相同的方式解决它:你处理文件的地方就是你的工作树。工作树中的文件是可延展的。提交中的文件不是。这意味着工作树与提交有根本的不同。工作树可能是 proposed 提交,但它仍然具有可塑性,因此它不是 actual 提交。 (它也没有任何元数据。)

因此,在 Git 中,工作树 没有哈希 ID 。但出于某种原因,Git 更进一步。 Git 添加了第三个实体,位于 之间 HEAD——当前提交——和工作——而不是仅仅让工作树成为提议的下一次提交树。第三个实体称为 index,或 staging area,有时甚至称为 cache。 (您将在 Git 文档中看到所有三个名称。它们都指的是同一件事。)此索引是 Git 存储建议的下一次提交的位置。 Git 然后提供像 git add 这样的命令,将 工作树(你有你的文件并可以处理它们的地方)复制 索引(更新提议的下一次提交)。

这意味着 git diff 需要能够:

  • 比较提交与提交
  • 比较提交与索引
  • 比较提交与工作树
  • 比较索引与工作树

它提供了四种不同的方法来执行此操作,具体取决于您传递给 的参数和 --cached 标志 git diff:

  • git diff <em>hash1</em> <em>hash2</em> 比较提交与提交
  • git diff --cached <em>hash</em> 比较提交与索引
  • git diff <em>hash</em> compares commit vs work-tree
  • git diff 比较索引与工作树

选择你想要的那个,添加-- <path>来限制diff输出,然后就大功告成了。