git-subtree without squash: view log
我使用不带squash选项的git子树add将一棵树合并到我的存储库中。Git日志显示提交已成功添加到存储库中。但是,如果我执行git log --follow filename,那么历史记录将在合并时停止,并且不会显示以前的提交。我试着用-M代替--follow,但也不管用。如何在合并之前从中获取特定文件的提交日志?
由git subtree merge或git subtree add创建的提交对来自子树的文件执行"添加",而不是"移动"。这意味着它们的历史不能像其他合并或运动那样被跟踪。
合并前直接在子树中查找,仍然可以显示所需文件的历史记录。如果您的工作区是创建git subtree的合并提交,那么它的第二个父级(HEAD^2将是原始子树的最后一个提交。从这里可以看到原始子树的内容:
1 2
| # Display the contents of the original subtree
git ls-tree HEAD^2 |
通过这个提交,您可以跟踪您感兴趣的文件的更改。请注意,您的文件在子树中的路径与工作区中的路径不同。您需要删除提供给git subtree的--prefix以获得正确的文件路径。
1
| git log HEAD^2 --follow -- path-in-subtree/file |
号
- 谢谢。由于这个问题,我们最终没有使用子树合并——如果我们使用两个单独的存储库,其他人更容易理解发生了什么。子树合并几乎可以被非高级git用户视为单个存储库,但像这样的小差异会让人感到困惑。所以我没有测试你的答案,但绝对值得投赞成票。
- 请注意,git过滤器树可以是此类内容的朋友。
实际上,git log --follow应该与子树合并一起工作,但众所周知,它很长一段时间都是黑客行为[1-3]。
我们可以坚持使用子树合并,并认为该策略对于跟踪多个历史是有效的,并且耐心等待git log --follow将改进的不可避免事件。这实际上可能是一个可行的决定,因为目前,git log --follow可以在非常有用的案例中看到一些历史。假设您将一个文件从顶级repo移动到了子repo,那么它就可以跟踪整个移动。当您想要跟踪特定于子回购的历史记录时,您必须有单独的副本或签出子回购分支。
备选方案和解决办法
您可以获取像这样的文件的日志[1]:
1
| git log -- '*filename' # from the toplevel |
这将查看每个接触到其名称的文件的提交以filename结尾。它不会跟随实际的重命名,并且可能显示为假如果有多个文件具有相同的基名称[1],则为正数。
您还可以使用不同的策略合并存储库。参考文献[4]显示了一种实现这一点的方法,它与常规子树合并非常接近,但具有可追踪的历史。基本上,你:
添加、获取和合并每个子存储库到顶级存储库作为常规的远程存储库,没有git子树或readtree。一开始,这会像是他们的根目录一样吹毛求疵,所以这要在项目生命的开始时完成。
git mv子repo文件到单独的文件夹
然后:
- 上游变更可以正常获取和合并,但使用-Xsubtree标志进行Git合并。
- 其他情况应该类似。我已经测试了向上游推进,它工作了,见[4]中的评论。
工具书类
[1]来自git邮件列表http://git.661346.n2.nabble.com/bug-files-are-losing-history-after-subtree-merge-td7597197.html
[2]来自git邮件列表http://git.661346.n2.nabble.com/gsoc-better-git-log-follow-support-td6188083.html a6188352
[3]git log --follow在谷歌的代码之夏https://git.wiki.kernel.org/index.php/soc2011ideas better git_log_uuu--follow_支持
[4]https://saintgimp.org/2013/01/22/merging-two-git-stores-into-one-repository-without-loss-file-history
- 我认为4应该是santgimp.org/2013/01/22/…
- @布莱恩拉森谢谢你
- 对于4,目前git log --follow只适用于文件,而不适用于文件夹。子回购文件夹中的git log --follow .不会返回子回购承诺,gitk --follow .也不会返回子回购承诺(git 2.10.1)。