14

I am using Git subtree to share a subfolder of my source code between projects. This is working alright, but every time I perform a git subtree push, the terminal shows an ever-growing list of commits:

git subtree push --prefix=public/js/engine engine-remote master --squash
git push using:  engine-remote master
-n 1/    1193 (0) 
-n 2/    1193 (1) 
-n 3/    1193 (2)
...
-n 1193/    1193 (1152)
Counting objects: 176, done.
...

Why is this and can I configure something differently to prevent this? I understand it needs to check the commits on the parent project, but I would expect it to be just to the point of the last successful pull from the subtree.

Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
Micros
  • 5,966
  • 2
  • 28
  • 34

1 Answers1

15

Answer 0

I don't use git-subtree in my daily workflow, so I had to research this a bit, but here you go:

git subtree push does git subtree split followed by git push. Command, that's showing this list of commits is actually git subtree split. If split doesn't find commit marked with aprropriate "git-subtree-dir:" line in commit message, then it goes through whole project history and creates new history, trimmed to single dir - in your case it must be doing just that.

How to avoid that?

After successfull git subtree push, you can do git subtree split --rejoin[1]. This will create empty merge commit, that will join history of subtree with history of your project; future calls to git subtree will use message from that merge commit when splitting history of subdir [2]. The same information should be placed in merge commit after git subtree pull, but often isn't (sometimes it is)[3]; you can do git subtree split after git subtree pull, but resulting graph looks ugly. See [3], please.

Answer 1

Is it really bad? It's nice to have this printed out. After each line carriage-return is printed, so I get nice "animation", that goes from 0 to n (in single line - not output, that you pasted in your question). Maybe your terminal doesn't recognize carriage returns (this might be an issue on Windows or OS X, I guess)? What OS do you use?

Answer 2

You can hide this with -q|--quiet if you can't use split --rejoin and this output really bothers you.

References and my comments

[1] but be aware! man page says:

If you do all your merges with '--squash', don't use '--rejoin' when you split, because you don't want the subproject's history to be part of your project anyway.

So use --rejoin if it's appropriate in your particular situation.

[2] Arguably this could be achieved better, but git-subtree cannot store this in commit object itself, because it's not native feature of git (yet?). It's bash script, that you can find in contrib/ directory: https://github.com/git/git/blob/master/contrib/subtree/git-subtree.sh That's probably reason, why documentation for this feature is scarce (hey, but man page is great).

[3] I experimented a bit and sometimes saw correct merge commit appear - somehow it seems related to situations, when git subtree pull resulted in conflict. This probably indicates bug in git-subtree.sh; give me more info, so I can investigate it further (and hopefully fix it). I looked through history of that file and saw no relevant fixes...

What version of git do you use? (mine is 1.9.3). What is your workflow with that shared directory? Was it git subtree added? Do commits flow both ways, or are they created in single repo only?

Patryk Obara
  • 1,847
  • 14
  • 19
  • First of all thanks a lot for your extensive answer, Patryk. After checking every day at first, I only just noticed your answer. – Micros Dec 02 '14 at 10:29
  • 1
    A question about your statement: _If split doesn't find commit marked with aprropriate "git-subtree-dir:" line in commit message_ What do you mean by this? How can I mark my commits like that? In response to your remarks: 1) I'm using OSX with ohmyzsh. 2) The situation you describe in [3] sounds a lot like what I keep running into. Part of this is probably because there are two people committing and pushing to the main projects. 3) I'm on 1.9.3 as well. 4) About my workflow, see next comment. – Micros Dec 02 '14 at 10:34
  • *How can I mark my commits like that?*. Example: add `file foo/foo` to your repo, then: `git subtree split --rejoin --prefix=foo -b foo_b` and look into msg of resulting merge commit. You can create such commit msg yourself, but you shouldn't. `subtree` cmd should create it for you during `subtree pull`, but sometimes it doesn't. – Patryk Obara Dec 04 '14 at 15:15
  • Great, I'll try that out. About our workflow: We have multiple projects that share the `public/js/engine` folder, but have their own `public/js/app` folder, and everything above it. Two people work on the projects and push/pull the projects to their respective remotes. When improving features, we sometimes have commits that contain changes to both project- and engine-files. We turned off rebasing in the _.git/config_ file. Only when we have a complete feature we push the changes in the engine folder back to the engine's remote subtree. Could this workflow be part of the problems? – Micros Dec 05 '14 at 16:46
  • 7
    "Is it really bad?" Oh, yes! It is really bad when you have a repository which is a couple of years old. I was just working on one which had **8525 previous commits** which took **22 minutes** to complete! – selfthinker Jan 14 '15 at 18:24
  • 1
    By "is it really bad" I referred to printing that output - would you rather have no output at all and sit in the dark for 22 minutes? That being said - 22 minutes is too long, it would be beneficial to measure why git is taking so long. Is your repo public by any chance, so I could investigate? – Patryk Obara Jan 19 '15 at 14:38