Git:如何列出提交中更改的文件,包括每个文件(blob)的 SHA-1 哈希值?

Ser*_*Ala 5 git

我想要什么,总结一下:

我有一个提交,例如HEAD111abc111,并且我想要一种优雅的方式来打印所有修改的文件,并且打印修改的文件及其 SHA-1 哈希值。我怎样才能做到这一点?

下面是一个几乎git-cat-file可行的想法,但它要么列出所有文件(包括未更改的文件),要么您必须在批处理模式下使用它。在批处理模式下使用它最初看起来很有希望,但我无法让它工作。请参阅下面的内容,了解我尝试过的事情等等。git-ls-tree

有关我的优先事项的说明,请参阅此问题的下文,或查看我自己写的答案(我不会接受,但也许您可以重构它)。

具体例子:

设置示例:

作为背景,让我们看看我的 Git 工作树是什么样子的:

$ ls

alice.txt
bob.c
carol.h
main.c

$ git status -s

# Nothing prints, the working copy is clean and untouched.
Run Code Online (Sandbox Code Playgroud)

我现在只更改两个文件:

$ echo "Add one line." >> bob.c

$ echo "Add one line." >> carol.h

$ git add .    # Add (stage) both changed files.

$ git status -s

M  bob.c
M  carol.h

$ git commit -m "Two changed files."

[master 111abc111] Two changed files.
 2 files changed, 2 insertions(+), 0 deletions(-)
Run Code Online (Sandbox Code Playgroud)

这几乎就是我想要的:

$ git cat-file -p 111abc111:./

100644 blob 99c2e88ad312f1eac63afc908f64c370fac9d947    .gitignore
100644 blob 607f8ea764981fb3f92a8d91abc2b154d99bc39c    alice.txt
100755 blob 5a297bd6931c1a70abbcab919815324258c08b0f    bob.c
100644 blob c6c2dfd18d26c1cf71b21e9d4c0892157dd6ec33    carol.h
100755 blob d0802cd238a3e83f186bc5c24be7e23dfc69205f    main.c
Run Code Online (Sandbox Code Playgroud)

上面命令的问题是它列出了指定路径中的所有内容,./在本例中是当前目录。它列出了每个文件,而不仅仅是修改过的文件。我只想让它显示bob.ccarol.h

第二个问题是,使用111abc111:./指定树状对象只会显示该目录中的文件(blob),而不会显示子目录中的文件。子目录将显示如下:

040000 tree b98f38763b689e8197c6129726d41169fceeaaa0    subdir
Run Code Online (Sandbox Code Playgroud)

可能的想法:

我刚刚删除了一些段落以及我尝试过的一些内容。

我怀疑密钥将用于git-diff创建在指定提交中已更改的“git 对象”(包括 blob)列表,然后以某种格式将该“git 对象”列表传递到git-cat-file. 所以像这样的神奇命令可能会起作用:

$ git diff 111abc111^ 111abc111 --magic-options-go-here | git cat-file --batch-check='%(objectname) %(objectsize)'
Run Code Online (Sandbox Code Playgroud)

关键是要找到 的值--magic-options-go-here。我也不确信git-cat-file管道字符右侧是我想要的,我可能想要其他东西。

谢谢。

编辑:我的优先事项

我对“git 对象”更感兴趣,即存储在 Git 中并由 SHA-1 哈希值标识的实体,例如树、blob、提交,也许还有其他我没有想到的东西,例如标签。如果您检查提交,我对文件名以及文件系统中的实际情况不太感兴趣。

我想查看 SHA-1 哈希值,这样我就可以看到“哦,这个合并提交指向另一分支中的树。通过在大型存储库中进行分支、合并和变基,每个提交对象都包含大量未更改的树和 blob,它们只是指针(引用),并且它们所引用的事物在概念意义上可能会非常遥远。当您仅更改一行,执行 git-commit,然后执行 git-push 并且推送的数据量为 50 MiB 时,这一点就会变得很明显。在内部,Git 只需取消引用大量指针并创建新的增量和包文件之类的东西。工作目录(文件系统)中看似微小变化的事情实际上可能代表 Git 存储库二进制格式的大量数据。

Jon*_*ely 1

我认为这符合你的要求:

git diff --stat --name-only $COMMIT^ $COMMIT \
  | xargs git ls-tree --full-tree  $COMMIT
Run Code Online (Sandbox Code Playgroud)

这可以放入别名中:

# Usage: git changed-files <commit>
# List files changed in a commit.
git config --local --add alias.changed-files '!f() { git diff --stat --name-only $1^ $1 | xargs git ls-tree --full-tree  $1 ; }; f'
Run Code Online (Sandbox Code Playgroud)

这是我的一个存储库的输出示例:

$ git changed-files d3a3029ca7489cb168d493de3d695809e84ffb0f
100644 blob 39855d9b6918f1c02f33115e357d7beeed1aaab8    libstdc++-v3/ChangeLog
100644 blob d0257c07e1fe92da339512d2457ac2ad43b12686    libstdc++-v3/include/std/optional
100644 blob 86b58ccf225597a64995878edc68c8666fa2c675    libstdc++-v3/include/std/type_traits
100644 blob 020cb26453f465ac49afb87f77e4833d0fb3aa16    libstdc++-v3/testsuite/20_util/optional/cons/value_neg.cc
Run Code Online (Sandbox Code Playgroud)

可以增强它以在给定两个参数时显示两个任意提交之间的更改:

# Usage: git changed-files <commit> [<commit>]
# List files changed in a commit (or between two commits).
git config --local --add alias.changed-files '!f() { git diff --stat --name-only ${2:-$1^} $1 | xargs git ls-tree --full-tree  $1 ; }; f'
Run Code Online (Sandbox Code Playgroud)