使用不合并的git-subtree命令:查看日志

18

我使用git subtree add而没有选用squash选项,将一个树合并到我的代码库中。使用git log可以看到提交成功地添加到了代码库中。然而,如果我运行git log --follow 文件名,历史记录会在合并处停止,不显示之前的提交记录。我尝试使用-M代替--follow,但也无法解决问题。如何获取合并之前特定文件或多个文件的提交记录日志?

2个回答

18

git subtree merge 或者 git subtree add 创建的提交行为是“添加”而非“移动”,这意味着来自子树的文件历史无法像其他合并或移动一样被跟踪。

要查看所需文件的历史记录,仍然可以通过直接查看合并前的子树来显示。如果您的工作区是由git subtree创建的合并提交,则其第二个父提交(HEAD^2)将是原始子树的最后提交。从这里可以查看原始子树的内容:

# Display the contents of the original subtree
git ls-tree HEAD^2

从这个提交开始,你可以跟踪你感兴趣的文件的变化。请注意,在子树中,你的文件路径将与你的工作区中的不同。你需要删除给 git subtree 输入的 --prefix 以便得到正确的文件路径。

git log HEAD^2 --follow -- path-in-subtree/file

4
谢谢。由于这个问题,我们最终没有使用子树合并 -- 如果我们使用两个独立的代码库,其他人会更容易理解正在发生的事情。对于非高级 Git 用户来说,子树合并几乎可以被视为单个代码库,但是像这样的细微差别可能会使人们感到困惑。所以我还没有测试过你的答案,但一定值得点赞。 - Bryan Larsen
1
请注意,git filter-tree 可以帮助您处理这种情况。 - Patrick Linskey

7

实际上,git log --follow 应该 能够处理子树合并,但已知其使用方法存在问题[1-3]。

你可以继续使用子树合并策略,并耐心等待不可避免的 git log --follow 改进。这可能是一个可行的决定,因为目前在某些有用的情况下,git log --follow 可以查看部分历史记录。例如,如果你将文件从顶级仓库移动到子仓库,则它可以跟踪完整的移动过程。当你想要跟踪特定于子仓库的历史记录时,你确实需要一个单独的副本或者检出子仓库分支。

替代方案和解决方法

你可以像这样获取文件的日志 [1]:

git log -- '*filename'          # from the toplevel

该命令可以查看涉及到以filename结尾的文件的每个提交记录。它不会跟踪实际重命名,并且如果您有多个具有相同基本名称的文件,则可能会显示错误结果[1]。
您还可以使用不同的策略合并存储库。Ref [4] 展示了一种非常接近于常规子树合并的方式,但具有可追溯的历史记录。基本上,您需要:
1. 将每个子存储库作为常规远程添加、提取和合并到顶级存储库中,而不是使用 git 子树或 readtree。首先,这将污染您的根目录,就好像它是他们的一样,因此这应该在项目启动时完成。 2. 使用 git mv 命令将子存储库文件移动到单独的文件夹中。
然后:
- 可以使用 -Xsubtree 标志对 git merge 进行正常获取和合并更新。 - 其他情况应该类似。我已经测试了向上游推送,它可以正常工作,请参见 [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 已在 Google Summer of Code 中使用https://git.wiki.kernel.org/index.php/SoC2011Ideas#Better_git_log_--follow_support - [4] https://saintgimp.org/2013/01/22/merging-two-git-repositories-into-one-repository-without-losing-file-history

1
我认为#4应该是https://saintgimp.org/2013/01/22/merging-two-git-repositories-into-one-repository-without-losing-file-history/。 - Bryan Larsen
对于#4,目前git log --follow仅适用于文件,而不是文件夹。在子存储库文件夹中执行git log --follow .将不会返回子存储库提交,gitk --follow .(git 2.10.1)也是如此。 - rfabbri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接