包含合并

时间:2018-06-06 11:17:06

标签: git

我正在编写一个脚本,该路径将路径作为参数并输出该路径的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 loggit 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-mergesgit 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的一些可能相关的事情:

  • History simplification上有一个很长的部分,也许有一些答案(还没有完全研究过)。
  • 关于log.follow配置(强调我的):如果为true,git log将表现为在给出单个时使用--follow选项。这与--follow具有相同的限制,即它不能用于跟踪多个文件,而在非线性历史记录上不能正常工作

#git IRC添加一些讨论:

[16:44]< + borekb>嗨,git loggit 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 loggit 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

中显示更多提交

1 个答案:

答案 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会做同样的事情&#34;剥离树&#34; 每个父级的操作。当您不使用--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 毕竟会变得无趣。