5

我正在尝试构建一个git log命令来检索具有以下属性的文件的历史记录(跟随副本和重命名):

  1. 我希望日志在注释之后“关闭”——也就是说,如果我git blame -elfwM在历史记录中提交任何提交(使用当时文件的任何名称),我希望注释中出现的每个提交也被载入史册。

  2. 我想知道历史记录中每个条目的文件原始名称。对于未重命名文件的提交,这将与文件名相同;对于这样做的提交,我想知道该提交的每个父级中的原始文件名。

  3. 对于文件的任何给定注释(在其历史记录中的任何时间点),我希望该提交的相应历史记录条目(我们知道从属性 1 中存在)使其作者、日期和文件名与作者、日期和文件名匹配注释的文件名。

  4. 满足(1),我希望尽可能少的额外提交。我特别想排除不会以任何方式影响文件的提交。

到目前为止,我能做的最好的事情是:git log --raw --follow -m --pretty="%H%n%P%n%aL%n%cs%n%s" -- FILENAME. 这是我在这条线背后的想法:

  • --follow应该完成以下重命名和副本的工作(但不给我文件名)
  • --pretty=...应该给我提交、父母、作者、提交日期和主题。我猜原作者+提交日期是什么git blame用途,但如果那是错误的,请纠正我。
  • --raw应该给我给定提交的原始文件名和新文件名。
  • -m应该拆分合并提交的条目,以便我可以获得单个父母的原始名称。

这在典型情况下似乎可以正常工作,但我编写了一个脚本来演示失败的场景。这是其中一次运行的示例输出:

Created git repository at /var/folders/y4/2t2n3dhj4bz4cwsrm801t_bm0000gn/T/tmp.Rtj55RWb
Committed: cbc8198fd5eb975ab5fc1fcc66889872429a40fe (master) Initial commit
Committed: 5628acbb478a8786eaec186bf4e6050142049848 (workbench) Renamed foo.txt to bar.txt
Committed: 2f6d49b3aa35ffa2953a65e21ba5c21d130fa3b1 (workbench) Modified line 3 of bar.txt.
Committed: bac0a739a1fd2acc7c0ce466d9055942cbf87ccb (workbench) Added dummy.txt
Committed: c018ca1b4436b73237c9a727ed2353cbd8152928 (workbench) Removed dummy.txt
Committed: 18bec91206357ec23ffe53a01d20ec64f7667e4e (master) Renamed foo.txt to baz.txt
Committed: a724f0cc49f39d9e99b8794b9f263efb5bc51da1 (master) Modified line 8 of baz.txt.
Committed: 4628679d5695c9a5fb080124b854f336fdf683d1 (master) Added dummy.txt
Committed: 58f700c48a16496dfd540126dab5e55952847993 (master) Removed dummy.txt
Committed: 633056c27cf0e3afb9529d478cf51ed0bdaa918e (master) Merged bar.txt and baz.txt as foo-merged.txt
----------------------------------------
633056c27cf0e3afb9529d478cf51ed0bdaa918e
58f700c48a16496dfd540126dab5e55952847993 c018ca1b4436b73237c9a727ed2353cbd8152928
john.doe
2021-04-10
Merged bar.txt and baz.txt as foo-merged.txt
:100644 100644 27393f0 bb5a6e5 R089     baz.txt foo-merged.txt

a724f0cc49f39d9e99b8794b9f263efb5bc51da1
18bec91206357ec23ffe53a01d20ec64f7667e4e
john.doe
2021-04-10
Modified line 8 of baz.txt.
:100644 100644 4f9956e 27393f0 M        baz.txt

18bec91206357ec23ffe53a01d20ec64f7667e4e
cbc8198fd5eb975ab5fc1fcc66889872429a40fe
john.doe
2021-04-10
Renamed foo.txt to baz.txt
:100644 100644 4f9956e 4f9956e R100     foo.txt baz.txt

5628acbb478a8786eaec186bf4e6050142049848
cbc8198fd5eb975ab5fc1fcc66889872429a40fe
john.doe
2021-04-10
Renamed foo.txt to bar.txt
:100644 000000 4f9956e 0000000 D        foo.txt

cbc8198fd5eb975ab5fc1fcc66889872429a40fe

john.doe
2021-04-10
Initial commit
:000000 100644 0000000 4f9956e A        foo.txt
----------------------------------------
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  1) This is line 1
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  2) This is line 2
2f6d49b3aa35ffa2953a65e21ba5c21d130fa3b1 bar.txt (<john.doe@gmail.com> 2021-04-10  3) Modified bar
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  4) This is line 4
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  5) This is line 5
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  6) This is line 6
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  7) This is line 7
a724f0cc49f39d9e99b8794b9f263efb5bc51da1 baz.txt (<john.doe@gmail.com> 2021-04-10  8) Modified baz
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10  9) This is line 9
cbc8198fd5eb975ab5fc1fcc66889872429a40fe foo.txt (<john.doe@gmail.com> 2021-04-10 10) This is line 10

第三行显示bar.txt在 2f6d49b3aa35ffa2953a65e21ba5c21d130fa3b1 中被修改。不幸的是,这个提交没有出现在历史记录中——我原以为它会因为 出现--follow,而​​且我还期望 633056c27cf0e3afb9529d478cf51ed0bdaa918e 有第二个条目,-m因为它有两个父母(我本来希望该条目有像:100644 100644 27393f0 bb5a6e5 R089 bar.txt foo-merged.txt) 这样的原始线。

注意:如果获取此信息是可以实现的,但不是在单个git log命令中,使用恒定数量的命令的解决方案也可以工作。我想避免做诸如递归检查注释以得出历史记录之类的事情,并且如果存在每行都更改的提交(例如,由于重新格式化),那么该特定策略也会失败。

4

0 回答 0