Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

git-subtree without squash: view log

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?

like image 587
Bryan Larsen Avatar asked Jun 06 '12 16:06

Bryan Larsen


People also ask

Should I use git subtree?

If there is an external repository you own and are likely to push code back to, use Git submodule since it is easier to push. If you have third-party code that you are unlikely to push to, use Git subtree since it is easier to pull.

How do I use Subtrees in git?

Adding a subtreeSpecify the prefix local directory into which you want to pull the subtree. Specify the remote repository URL [of the subtree being pulled in] Specify the remote branch [of the subtree being pulled in] Specify you want to squash all the remote repository's [the subtree's] logs.

What is prefix in git subtree?

The –prefix parameter defines the root directory for the cloned repository, then add the remote url, the branch and let it squash the entire commit history (–squash). Git doesn't like uncommitted changes so make sure to stash/commit any existing changes before adding a new subtree.

What is git subtree split?

This takes advantage of the fact you want to move to another repo, so we can extract the subtree, and then relocate it in separate steps. Use git subtree split to extract the files you want to the an intermediate branch in your repository (you have already done this). git subtree split -P lib3 -b new-branch.


2 Answers

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
like image 134
Maic López Sáenz Avatar answered Sep 16 '22 14:09

Maic López Sáenz


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

like image 35
rfabbri Avatar answered Sep 20 '22 14:09

rfabbri