我正在编写一个脚本,该路径将路径作为参数并输出该路径的Git提交,类似于GitHub在您单击某个文件夹中的 History 按钮时所执行的操作(此处为&# 39; s an example)。本质上,我想写这样的脚本:
git log -10 --oneline -- "$directory"
但是,我在为根文件夹和子目录以及follow
行为的各种配置可靠地工作方面遇到了很多麻烦。在下面的实验之后,我也认为我误解了git log
首先如何处理各种旗帜,所以如果有人能帮助我理解这一点,那将会很棒。
注意:在我们的情况下,我们有时需要传递多个目录,这就是为什么我试图使pathspec工作,而不是像
cd subdirectory && git log
那样。
示例来自versionpress/versionpress
存储库(处于2071052a状态),我已经在Git for Windows 2.17.1.windows.2和Linux上使用Git 2.14.1进行了测试。
首先,docs
文件夹的基本日志:
$ git log -10 --oneline -- docs
81554a46 Small updates of Dev-Setup.md
84d3229e Updated intro message to mention beta instead of alpha
8244d42a Added link to announcement blog post
da97c7c3 Merge branch 'master' into 1263-pre-4.0beta-polish
5c99bc30 Merge pull request #1270 from versionpress/4.0-beta-release-notes
f22b0e27 4.0-beta release notes updated, are now close to final
f0de171f Specific WordPress version used in dev-env Dockerfile, Dev-Setup slightly updated
bcd6d4e8 package-lock JSONs updated for npm 5.1 (there were some issues reported with 5.0)
1438bc43 Documented running tests by picking a test suite from phpunit.xml, the "other tests" documented in more detail
5af500d4 Better instructions on running specific tests from CLI, tests' docker-compose.yml cleaned up, various other testing "readme" updates
好,这是same as on GitHub。
现在,根目录也一样:
$ git log -10 --oneline -- .
94084136 Typo in the activation message
8a15a8b1 Added error when re-activating VP with WP CLI
6ad07b7d package-lock.json updated
e7e356f8 Updated WP and WP-CLI versions in ext-libs
777e2d05 Disable event propagation after click on the commit table checkbox
81554a46 Small updates of Dev-Setup.md
32d6dbe2 Installed WordPress version bumpted to 4.9
459c2e6d package-lock.json updated for npm 5.5
77ad593c Link to Gitter and support repo in ISSUE_TEMPLATE.md
84d3229e Updated intro message to mention beta instead of alpha
不好,合并提交丢失了。我可以删除路径规范来获取它们:
$ git log -10 --oneline
2071052a (HEAD -> master, temp/master, origin/master, origin/HEAD) Merge pull request #1318 from aidik/master
94084136 Typo in the activation message
129bf972 Merge pull request #1314 from x1024/master
8a15a8b1 Added error when re-activating VP with WP CLI
288e305d Merge pull request #1310 from versionpress/1307-wp-update-fixes
6ad07b7d package-lock.json updated
e7e356f8 Updated WP and WP-CLI versions in ext-libs
f8d22592 Merge pull request #1309 from versionpress/1308-fix-commits-table-checkboxes
777e2d05 Disable event propagation after click on the commit table checkbox
06208405 Merge pull request #1307 from versionpress/wp-4.9-for-test-sites
但这对我的剧本来说是不切实际的,而且我认为自己做错了,因为我认为git log
和git log -- .
的输出应该相同,不应该吗?
从我的实验中,--full-history
标志似乎在.
目录上运行时添加了合并提交:
$ git log -10 --oneline --full-history -- .
2071052a (HEAD -> master, temp/master, origin/master, origin/HEAD) Merge pull request #1318 from aidik/master
94084136 Typo in the activation message
129bf972 Merge pull request #1314 from x1024/master
8a15a8b1 Added error when re-activating VP with WP CLI
288e305d Merge pull request #1310 from versionpress/1307-wp-update-fixes
6ad07b7d package-lock.json updated
e7e356f8 Updated WP and WP-CLI versions in ext-libs
f8d22592 Merge pull request #1309 from versionpress/1308-fix-commits-table-checkboxes
777e2d05 Disable event propagation after click on the commit table checkbox
06208405 Merge pull request #1307 from versionpress/wp-4.9-for-test-sites
然而,"打破" docs子目录(注意第一个不应该存在的合并提交):
$ git log -10 --oneline --full-history -- docs
06208405 Merge pull request #1307 from versionpress/wp-4.9-for-test-sites
81554a46 Small updates of Dev-Setup.md
84d3229e Updated intro message to mention beta instead of alpha
8244d42a Added link to announcement blog post
9671af87 (tag: 4.0-beta) Merge pull request #1283 from versionpress/1263-pre-4.0beta-polish
da97c7c3 Merge branch 'master' into 1263-pre-4.0beta-polish
5c99bc30 Merge pull request #1270 from versionpress/4.0-beta-release-notes
f22b0e27 4.0-beta release notes updated, are now close to final
f0de171f Specific WordPress version used in dev-env Dockerfile, Dev-Setup slightly updated
bcd6d4e8 package-lock JSONs updated for npm 5.1 (there were some issues reported with 5.0)
这可以修复"添加--simplify-merges
:
$ git log -10 --oneline --full-history --simplify-merges -- docs
81554a46 Small updates of Dev-Setup.md
84d3229e Updated intro message to mention beta instead of alpha
8244d42a Added link to announcement blog post
da97c7c3 Merge branch 'master' into 1263-pre-4.0beta-polish
5c99bc30 Merge pull request #1270 from versionpress/4.0-beta-release-notes
f22b0e27 4.0-beta release notes updated, are now close to final
b8a138ce Fixed path of plugin definition discovery
48333d82 4.0-beta release notes written (some TODOs still remaining)
2c61613f 4.0-alpha1 Markdown file renamed to such (used to be just 4.0) and updated to contain the same info as the GitHub release page
f0de171f Specific WordPress version used in dev-env Dockerfile, Dev-Setup slightly updated
但这也会给.
目录带来麻烦:
$ git log -10 --oneline --full-history --simplify-merges -- .
94084136 Typo in the activation message
8a15a8b1 Added error when re-activating VP with WP CLI
6ad07b7d package-lock.json updated
e7e356f8 Updated WP and WP-CLI versions in ext-libs
777e2d05 Disable event propagation after click on the commit table checkbox
81554a46 Small updates of Dev-Setup.md
32d6dbe2 Installed WordPress version bumpted to 4.9
459c2e6d package-lock.json updated for npm 5.5
77ad593c Link to Gitter and support repo in ISSUE_TEMPLATE.md
84d3229e Updated intro message to mention beta instead of alpha
我按照建议here尝试了-m
标记但没有区别。
现在,用户的配置中log.follow
设置为true
,还有一些我不完全理解的行为。
$ git config --global log.follow true
(empty output)
$ git log -10 --oneline --merges -- .
(empty output)
即使被要求,也没有合并提交。我需要添加--no-follow
(可能应该在Git文档中记录):
$ git log -10 --oneline --merges --no-follow -- .
da97c7c3 Merge branch 'master' into 1263-pre-4.0beta-polish
5c99bc30 Merge pull request #1270 from versionpress/4.0-beta-release-notes
aba96d3f Merge pull request #1277 from versionpress/1274-using-filter-on-init
82a3fd4e Merge pull request #1269 from versionpress/ext-libs-install-locked
ccb74422 Merge pull request #1251 from versionpress/1120-edit-update-action
a94dc0d3 Merge pull request #1246 from versionpress/1176-plugin-definition-discovery
ae530356 Merge pull request #1260 from versionpress/1154-temp-in-zip
ffd7647e Merge pull request #1170 from versionpress/1168-getmenureference-broken
f4a00328 Merge branch 'master' into 1120-edit-update-action
7b29e7ed Merge branch 'master' into 1041-dockerized-dev-setup
所以我希望添加--no-follow
并删除--merges
会产生预期的输出,但是,在这种情况下它仍然会错过合并提交:
$ git log -10 --oneline --no-follow -- .
94084136 Typo in the activation message
8a15a8b1 Added error when re-activating VP with WP CLI
6ad07b7d package-lock.json updated
e7e356f8 Updated WP and WP-CLI versions in ext-libs
777e2d05 Disable event propagation after click on the commit table checkbox
81554a46 Small updates of Dev-Setup.md
32d6dbe2 Installed WordPress version bumpted to 4.9
459c2e6d package-lock.json updated for npm 5.5
77ad593c Link to Gitter and support repo in ISSUE_TEMPLATE.md
84d3229e Updated intro message to mention beta instead of alpha
这与上述行为一致,但我仍然不理解:我认为git log
基本上是git log --no-merges
和git log --merges
的组合输出,但它&# 39;当指定路径时不是这种情况。
对此的任何解释都将非常感激。
UPDATE :可能问题不在于合并提交与普通提交。我已尝试使用其他仓库并在未指定路径时比较输出.
$ git log -10 --oneline --no-follow
350df16f6 (HEAD -> master, origin/master, origin/HEAD) Merge pull request #1977 from versionpress/1975-do-not-upgrade-deleted-sites
21db78245 Merge branch 'master' into 1975-do-not-upgrade-deleted-sites
0a4eda432 Upgrading only sites that are not deleted
43cd96ac9 Merge pull request #1971 from versionpress/fix-ui-creation-of-sites
a952ae1c5 Merge pull request #1966 from versionpress/1949-reduce-db-migrate-boilerplate
018e4d3b7 Merge pull request #1969 from versionpress/1964-platform-api-easy-local-run
4515bc242 Fix add a new site button
6e4ecd652 Merge branch 'master' into prod
4229e326a Fixed Makefile of default-backend
fc99e0f19 [hotfix] Disabled removing TLS hosts
$ git log -10 --oneline --no-follow -- .
21db78245 Merge branch 'master' into 1975-do-not-upgrade-deleted-sites
0a4eda432 Upgrading only sites that are not deleted
43cd96ac9 Merge pull request #1971 from versionpress/fix-ui-creation-of-sites
a952ae1c5 Merge pull request #1966 from versionpress/1949-reduce-db-migrate-boilerplate
018e4d3b7 Merge pull request #1969 from versionpress/1964-platform-api-easy-local-run
4515bc242 Fix add a new site button
4229e326a Fixed Makefile of default-backend
fc99e0f19 [hotfix] Disabled removing TLS hosts
d1bcdae2d Replace 'db-migrate-boilerplate' with a custom implementation
c60032144 Kubernetes.ts returned to its original, non-async structure before 36308d3 with the token loading logic moved to `server.ts` (it didn't really belong to Kubernetes.ts).
它只是一组不同的提交,我在这里看到包含/排除提交的明确模式......
来自git-log docs的一些可能相关的事情:
log.follow
配置(强调我的):如果为true,git log将表现为在给出单个时使用--follow选项。这与--follow具有相同的限制,即它不能用于跟踪多个文件,而在非线性历史记录上不能正常工作。 从#git
IRC添加一些讨论:
[16:44]< + borekb>嗨,git log
和git log -- .
会产生相同的结果吗?似乎后者缺少一些合并提交,有时候,我不太明白为什么
[16:45] borekb:这可能取决于你所在的目录?
[16:45]< + borekb>我在一个项目的根目录中
[16:45]< + borekb>我在这里发布了一些例子:Git log for a directory including merges
[16:46]< + borekb>老实说,我不明白发生了什么:)我觉得我必须遗漏一些明显的东西,因为git log
是一个基本的命令,我已经使用了一百万次,尽管没有路径符合规范
[16:48] borekb:这可能是"历史简化"。它是关于man git log的描述
[16:48]< @ gitinfo> borekb:git-log联机帮助页面位于https://gitirc.eu/git-log.html
[16:49] borekb:哦,基于SO看起来你已经走上了正轨
[16:50]< + borekb> rafasc:我也怀疑它是这样的(直接链接:https://git-scm.com/docs/git-log#_history_simplification),但是假设默认情况下git log
和git log -- .
应该"简化"相同的输出?
[16:50]< + borekb>当我试着阅读那部分时,我的头部爆炸了一点:)
[16:51]我认为答案是否定的。假设这是不安全的。 - 是历史简化的一种形式。所以你要告诉git你想要简化
[16:54]< + borekb>好点
[16:56]< + borekb>从我的实验中看,-- path
在某个子文件夹(git log -- docs
)与当前目录(git log -- .
)之间的行为方式不同。
[16:56]< + borekb>子文件夹按预期工作,.
产生我不太了解的结果
[16:57] borekb:它与手册页上的那个部分有关,它描述的是什么是TREESAME,什么不是什么。
[16:57] borekb:尝试dummy_folder / ..:P
[16:59]< + borekb> up_here:聪明的黑客,但不起作用:)
[17:01] borekb:无关,但是当使用在线检查提交时,你可能想使用--show-linear-break,以便理解提交之间的关系。 (注意--graph --online也可能会产生误导,图形需要至少两条线来绘制边缘,在这种情况下, - pretty = short很有用)
[17:02]< + borekb>拉法斯克:哦,那太好了
[17:03]< + borekb> rafac:你如何估计出现一组旗帜的可能性会导致git log -- .
产生与git log
完全相同的输出?在我深入参加TREESAME讨论之前,我一直在询问将对我来说是痛苦的:)
[17:05] borekb:从记忆中,我会说 - 完整的历史...但你有问题吗?
[17:06]< + borekb> rafasc:是的, - full-history会在git log -- subdirectory
答案 0 :(得分:3)
你确实被历史简化所困扰。请注意,在使用git log
的任何路径名时,默认情况下会启用简化。如果您不提供路径名,则默认情况下不。添加特定选项,例如--full-history
或--simplify-*
(由于--follow
设置为log.follow
,您可能也会被隐含的true
所咬,但是很难看出这种情况会发生在哪里。 )
通过执行非常有限的git diff
来简化。请记住,当git log
遍历提交图时,它一次只能处理一次提交 C 。每个提交 C 都有一些父提交。对于普通(非合并)提交,只有一个父级,因此对于要检查的 C 中的每个文件 - 基于您给出的路径名 - 中的该文件C 与其父 P 中的文件100%完全相同,或者它有所不同,Git很容易分辨,因为路径是100%两个提交中的相同内容在提交的附加树中具有相同的 blob哈希。
the documentation中的TREESAME表达式意味着什么:我们采用提交 C 树,删除所有不是' t 正在检查,留下(在内存中 - 这不会影响存储在存储库中的任何内容!)一个附加到 C 的骨架树,其中包含 的文件正在接受审查然后我们采取(单)父 P 并做同样的事情。结果是匹配 - C ,其父 P 是TREESAME或不匹配。
提交是有趣的"如果它有趣,将会显示。即使它不感兴趣,Git仍然会将父 P 放入图形遍历优先级队列中以便稍后检查,因为这只是一个普通的提交而且Git 必须走过它来构建历史。 (这里有一些奇怪的问题"父母重写"我会跳过,虽然这对--graph
很重要。)
然而,在合并,情况有所不同。提交 C 仍像往常一样拥有一棵树,但它有多个父提交 P i 。 Git会做同样的事情"剥离树" 每个父级的操作。当您不使用--full-history
时,Git会比较 C 的精简树与每个 P i 。如果它不是任何父级的TREESAME,则包含合并本身,但如果它 TREESAME至少一个父 P i < / sub> ,合并往往被排除(取决于其他选项)和 Git将仅 该父项放入优先级队列以便遍历图形。如果 C 是TREESAME到多个P i P j P k ...,Git默认选择其中一个父母并丢弃其余的父母。
添加--full-history
会禁止丢弃除 P i 之外的所有内容。所以现在Git将走向合并的所有父母。这并不影响合并本身是否显示,它只是确保Git同时走两边&#34;合并,或所有武器,如果它是一个多向章鱼合并。
这里的逻辑是,如果您正在查看的文件在提交 C 中提交,并且提交 P i ,为什么然后,你不关心他们在其他一些父母 P o <中 / sub> ,因为该文件的当前形式是由于父 P i 而不是父 P o < / em>。如果您认为您正在查看的文件正确,则此逻辑是正确的,但如果您认为它们错误则会崩溃>并且您正在寻找失去所需更改的合并。
--follow
(因为你的路径名是.
,而Git通常根本不做目录 - 使用目录名实际上意味着目录下任何地方的所有文件,递归地 - 这不应该&#但是,如果您使用文件名称,则可能很重要。请记住,只有在您正在查看一个文件时才会遵守--follow
。)
--follow
的工作方式,这就是它只适用于一个路径名的原因(并且不应该是.
作为路径的问题),就是当Git是这样做选择我们走过提交图时我们走的提交是否有趣,因此应该显示测试,它会在每次提交时执行这些git diff
vs其父母。
与TREESAME差异不同,--follow
测试是一个完全差异 - 它比快速100% - 同样更昂贵,至少对于更有趣的问题案例 - 但它&#39 ; s仅限于一个文件,这使其免于太代价高昂。它也仅适用于单父提交,尽管这是在--first-parent
之后(如果你使用它)剥离其他父项或在-m
之后(如果你使用它)将合并分成多个虚拟提交共享同一棵树,或者历史简化之后只选择了一个父级。 1 在任何情况下,如果父级没有一个带有(单个)路径名的文件,那么你可以使用它。重新记录,Git完成父和子的完全差异,看它是否可以在父级中找到一些重命名的文件。如果它可以找到这样一个重命名的文件,首先它会显示子文件 - 因为文件发生了变化:它至少在重命名之后 - 然后Git 更改了它正在查找的路径名,因为它遍历孩子的父母。
也就是说,Git开始寻找dir/sub/file.ext
,点击提交 C ,其中 C 的父没有&#39 ; t 一个dir/sub/file.ext
,做了一个完整的差异,并找到了一个名为path/to/old.name
的足够相似的文件。所以Git显示你提交 C ,说R<percent> path/to/old.name -> dir/sub/file.ext
,然后转到 P - 但现在不是寻找路径dir/sub/file.ext
的更改,它正在寻找路径path/to/old.name
的更改。
这个特殊的技巧无法在所有合并中运行良好:文件可以在合并的各个部分中重命名,也可以在多个臂中重命名,具体取决于关于谁进行了重命名以及何时进行。 Git只能查找一个路径名 - 它不会继续查找这两个名称。当然,提供路径名称可以简化历史记录,因此通常不会担心任何合并。合并案例仅在您使用--full-history
或--simplify-merges
等标记时才会发生。
1 请注意,如果历史简化从合并中选择了一个父级,则它在剥离后选择了 P ,即TREESAME为 C 除了我们关心的文件之外的所有文件 - 因此根据定义,我们在 C 中--follow
的一个文件与父 P <中的同名文件匹配/ em>的。这意味着提交 C 毕竟会变得无趣。