git 中文件的最后一次提交显示添加的行但文件不在项目文件夹中

The last commit of a file in git shows lines added but the file is not in the project folder

使用命令 git log --numstat 我可以看到文件 MyFile 的最后一次提交显示添加了一些行。这意味着它对 MyFile 所做的最后一件事是有人向其中添加了一些行。

同时我在项目文件夹中找不到MyFile。因此,我假设 MyFile 在某些分支中被引用,但在当前分支中没有被引用。

这是一个正确的假设吗?如果是这样,有没有办法找到哪些分支实际上引用了 MyFile?

一样,默认情况下,git log 从当前或 HEAD 提交开始,然后从那里向后工作。所以:

$ git log
commit cefe983a320c03d7843ac78e73bd513a27806845 (HEAD -> master ...
...
5       0       Documentation/RelNotes/2.34.0.txt

commit 45d141a1ddbc55c220ad4c726c02bbbf7a69247a
  :
  :

commit 187fc8b8b6e7a2b65f7c74cfaa8aa6bad36a18b2
...
29      15      unicode-width.h

这里我们看到 unicode-width.h 在提交 187fc8b8b6e7a2b65f7c74cfaa8aa6bad36a18b2 中被修改了。只需从 numstat 输出中向上读取一点,即可找到提交哈希 ID,其中,根据 git diff 的结果,父对子对给定文件进行了给定更改。

At the same time I can not find MyFile in the project folder. Therefore I assume that MyFile is referenced in some branches but not in the current branch.

Branches(分支名称)无关;只有 提交 重要。每个提交都在零个或多个分支上,因此提交 187fc8b8b6e7a2b65f7c74cfaa8aa6bad36a18b2 可能在 27 个分支上,或者只是在 master 上(它肯定在 master 上,因为我的 git logHEAD 其中 命名为 master)。文件 unicode-width.h 肯定在该提交中。

一个文件是否在你的工作树中也不是真正相关的,但是如果一个文件MyFile 在你的工作树中,运行:

git log MyFile

通常会给你一个错误。然而:

git log -- MyFile

不会给你报错。原因是这里,git log知道使用MyFile作为路径名:

$ rm Makefile
$ git log Makefile
fatal: ambiguous argument 'Makefile': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Git 正在尝试将 Makefile 视为哈希 ID(它不能是一个:其中包含一些错误的字母;badf00ddeadcabfeedc0ffee 可以是缩写的哈希 ID,但 c0mmand0 不能,因为 mn 都不是有效的十六进制数字),或者作为分支或标签名称(但它不是一个)或其他查找提交的方法:请参阅 the gitrevisions documentation 以了解许多 多种 指定特定提交的方法。然而,-- 语法告诉 Git 命令后面是 而不是 一个选项,即使它类似于一个选项,在这种情况下 也不是 修订说明符。所以 git log 现在将其视为文件名:

$ git log -- Makefile
commit 8f79fb6445cb1d17c5527ba958e460725e7b111e
Merge: 68658a867d 32da6e6daf
Author: Junio C Hamano ...

(当然,我可以用 git restoregit checkoutgit reset --hard 或其他方式恢复我删除的文件,我这样做是因为我真的不想删除它) .

如果出现以下情况,则可以解释为:

  1. 文件在分支A被删除
  2. 同一个文件在分支 B 删除发生后被修改(按时间)。
  3. B分支合并到A分支,导致冲突,选择删除

这里有一个示例 bash 脚本来演示这一点:

#!/bin/bash -v

git init

echo asdf > asdf.txt && git add . && git commit -m "Add file asdf.txt"

git branch test-branch

rm asdf.txt && git add . && git commit -m "Delete asdf.txt"

git switch test-branch

sleep 1 # pause for one second to make sure commit datetimes are different

echo qwer >> asdf.txt && git add . && git commit -m "Add qwer to asdf.txt"

git switch main

git merge test-branch --strategy=ours --no-edit # cheat to prevent a conflict and skip the other commit

ls -la # prove there are no files

git log --numstat # the most recent commit of asdf.txt is adding a line