code54 / buildversion-plugin

A maven plugin that extracts current build information from git projects
34 stars 9 forks source link

Build-tag-delta can be decreasing?! #9

Open jfrantzius opened 10 years ago

jfrantzius commented 10 years ago

Hi,

in our git repo we have a single tag that points to the very first commit. There are no other tags anywhere.

I just had the situation where my build yielded a build-tag-delta of 174, then I pulled some commits from remote (with rebasing), and afterwards the build-tag-delta was set to 170, so it decreased by 4!?

Is this behaviour by design for certain cases, or is this a bug maybe? I was hoping that the build-tag-delta would be a strictly monotonically increasing number...

It seems we saw the same happening on our CI server, which always simply clones the remote repo.

Cheers, Jörg

jfrantzius commented 10 years ago

OK, only now I (hopefully) fully understand what it means that the Git history is a directed acyclic graph (as can be seen e.g. in http://eagain.net/articles/git-for-computer-scientists/#history ). A new merge commit may mean that a different path is taken through the history, with fewer commits than the commit before.

For the same tag, build-tag-delta could be a strictly monotonically increasing number if always the longest path was chosen. That wouldn't be trivial to implement I guess, but luckily it's at least solvable in linear time. If the commit generation numbers were accessible, this could be commit generation number minus tag's commit generation number.

Always taking the longest path instead of the "first parents" path could detect unwanted tags from branches again, but then I'm not sure the "first parents" approach keeps us save from them anyway BTW...

That could be solved if buildversion-plugin didn't guess the nearest tag by itself, but accepted the target tag as a configuration parameter. Not sure how that fits with the release plugin though...

dobladez commented 10 years ago

May be your decreasing number happened simply because you did a rebase. Rebase effectively re-writes your commit history, therefore, anything can change.

Now, assuming no rebases happened: If you always run git-merge from "your" branch (I mean, the branch from where you run the plugin), then the delta number should always increase, since the walking logic will not even "see" the other side of a merge (it always follows the first-parent, the paths lengths make no difference). May be you've run the plugin from different branches?

The main reason to follow first-parent is to avoid picking tags from another branch. If you haven't yet, take a look here for some explanation regarding git-describe and why the plugin follows first parents instead: https://github.com/code54/buildversion-plugin#about-git-describe.

Thanks

jfrantzius commented 10 years ago

Thanks for your answer. The problem with first-parent is that merge commits happen also on the same (named) branch. The following shows the git history of Alice and Bob working on the master branch. There is a merge commit at the top where Bob wasn't able to rebase his changes before pushing them, so he had to merge:

image

Now if our CI server sees Alice' commit first, the build-tag-delta will be something >3, and when it sees Bob's pushed merge commit, it will be less. That's because Bob's unnamed branch is the first parent of his merge commit, and its path so shortcuts a number of commits by Alice.

Merges don't only happen between named branches. When two developers start basing their commits on the same parent commit, they are implicitly branching, and their changes may require a merge commmit in the future.

Chosing first-parent here is very arbitrary, because it means chosing a developer's unnamed branch, and that depends only on who is doing the merge and push first.

dobladez commented 10 years ago

Ah, I see you case now: "back-merges". I cannot think of a quick and easy solution to that case :-\

I guess I never run into this before because I (almost?) never do back-merges... they clutter history. I found this discussion relevant for a team I worked with recently.

That said, I'm certainly open to try to find a robust solution if at possible. Like you said: if git provided commit generation numbers, that would help.

We'd still have to resolve the case where tags appear within the merged paths. In your example you are assuming the tag is set before Alice's and Bob's histories diverged... but there are valid cases where tags will be only on one side. Again, this is what the first-parent idea is trying to solve.

IMHO, passing as argument the name of the tag you want to look for kinda defeats the purpose of using this plugin to begin with... although it might be useful for some. One simple idea to count commits here would be to simply call git log without --first-parent (which logs all commits from all paths); in your example it'd count all of Alice's and Bob's commits. What I don't like about this is that passing the tag name would give a different number than when the plugin finds the tag by itself. Hmmm... may be the plugin could use first-parent to find the tag, and then a simple log (counting all commits) to do the count?. Again: the case of doing back-merges which contain tags in them would screw things up... but hey, we cannot do magic here.