我有一个提交,例如HEAD或111abc111,并且我想要一种优雅的方式来打印所有修改的文件,并且仅打印修改的文件及其 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.c和carol.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 存储库二进制格式的大量数据。
我认为这符合你的要求:
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)
| 归档时间: |
|
| 查看次数: |
3341 次 |
| 最近记录: |