Вопрос

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?

Это было полезно?

Решение

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:

  1. 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.
  2. 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

Другие советы

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top