问题
I merged a tree onto a my repository by using git subtree add without the squash option. A git log shows that the commits were successfully added to the repository. However, if I do a git log --follow filename
, the history stops at the merge and does not show previous commits. I tried using -M
instead of --follow
and that doesn't work either. How can I get a log of the commits for a specific file or files from before the merge?
回答1:
Actually, git log --follow
should work with subtree merges, but it is known to be hackish for a long time [1-3].
One can stick with subtree merges and rest asured that the strategy is valid for tracking multiple histories, and patiently wait for the unavoidable event that git log --follow
will improve. This may actually be a viable decision, since at present git log --follow
can see some history in very useful cases. Say you moved a file from the toplevel repo to a sub-repo, then it can track the full move. When you want to track the history that is specific to a sub-repo, you really have to have a separate copy or check out a sub-repo branch.
Alternatives and Workarounds
You can get logs for the files like this [1]:
git log -- '*filename' # from the toplevel
This views each commit that touched a file whose name
ends with filename
. It won't follow actual renames, and may show false
positive if you have several files with the same basename [1].
You can also merge the repositories using different strategies. Ref [4] shows a way to do this which is very close to what you have with regular subtree merging, but with traceable histories. Basically, you:
- add, fetch and merge each sub-repository to the toplevel repository as a regular remote, no git subtree or readtree. At first, this will polute your root dir as if it was theirs, so this is to be done at the beginning of a project's life.
git mv
the sub-repo files to separate folders
Then:
- upstream changes can be fetched and merged normally, but with the
-Xsubtree
flag to git merge. - other cases should be similar. I've tested pushing upstream and it works, see comment in [4].
References
[1] From the git mailing list http://git.661346.n2.nabble.com/Bug-Files-are-losing-history-after-subtree-merge-td7597197.html
[2] From the git mailing list http://git.661346.n2.nabble.com/gsoc-Better-git-log-follow-support-td6188083.html#a6188352
[3] git log --follow
has been in 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
回答2:
The commit created by git subtree merge
or git subtree add
does an "add" for the files coming from the subtree, not a "move". This means that their history cannot be tracked as with other merges or movements.
History for the file you want can still be displayed by looking directly in the subtree before the merge. If your workspace is the merge commit that git subtree
created then the second parent of it (HEAD^2
) will be the last commit of the original subtree. From here you can see the contents of the original subtree:
# Display the contents of the original subtree
git ls-tree HEAD^2
From this commit you can track the changes of the file you are interested. Be careful that the path of your file will be different within the subtree that in your workspace. You will need to remove the --prefix
given to git subtree
in order to have the correct path for your file.
git log HEAD^2 --follow -- path-in-subtree/file
来源:https://stackoverflow.com/questions/10918244/git-subtree-without-squash-view-log