Hello,
This is not so much a question about git, but more about history organisation.
I'm undecided on the best way to deal with bug fix history.
Imagine this situation:
* -- * -- B -- * -- * -- *
"B" is a commit that introduced a feature and a bug, that bug is present
forever more in history (which I think is good - history is history). I've
pushed the repository to the rest of the developers in the meantime, so there
is no editing "B" and doing some rebase magic.
Now, I want to make a commit that fixes that bug. These are the options:
* -- * -- B -- * -- * -- * -- F
or
* -- * -- B -- * -- * -- * -- M
\ /
--------------- F
That is - just commit a fix or, commit the fix, "F", directly on "B" then
merge that fix back to HEAD with "M".
I quite like option 2 because it records intent - i.e. "I wish I could have
gone back and changed this revision, but I can't", but it makes a more
complicated history.
What do people think?
Andy
--
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
-
I just encountered this myself with one of my repos. I'm developing solo so I could just rebase if I felt like it, but don't like developing that habit, so I'm probably going with the second one. But that's because of how I'm developing it. My master has undergone serious changes recently (since the bug commit), so I'm going back and checking out the bug commit to focus on that issue without anything else that's been changed since then. My personal feeling is that the commit should reflect how the fix was developed. If it's simple fix that you simply wrote on top of the full branch, commit it that way. If you had to (or wanted to) go back and develop on top of the original commit, commit it that way. Usually I'll just commit on top of master, but if either I need to remove other complications from the fix or need to introduce the fix (but not everything else) into multiple branches, I'll do the merge. ~~ Brian -
I think that largely depends on your taste and what other things you have between B and the tip when you contemplate on the fix. If you ever have a forkpoint (e.g. maybe soon after B you had a tagged release, and maintenance track for that forked from it), then the latter is much more manageable in the long run. That is how 'master' and 'maint' in git.git are managed. An old bug is fixed as close to the introduction of bug as practical (so I would _not_ fork a fix on top of B itself, but apply fix to the tip of 'maint'), and then all newer development track that contain breakage B merges the fix from that branch (i.e. 'maint' is then merged into 'master' to propagate the fix forward). The way 'next' and 'master' works in git.git looks a bit different from it, but you will realize that the idea is the same if you look at individual topic branches. Each topic is forked from 'master', gain its own commits and merged to 'next'. Its bugs may be discovered later while it still hasn't been merged to 'master'. I'd _never_ commit a fix to 'next' directly, but a fix goes to the tip of the topic branch that introduces the bug, and then merged to 'next'. When the topic is reasonably bug-free, it then is merged to 'master' -- at that point, the history of the topic has all the relevant fixes. If you think of your straight single strand of pearls (the first picture) as a degenerated case that has a topic that includes B and ends with the tip, "merged" to 'master' in a fast forward fashion (i.e. the rightmost commit in the picture is the tip of the topic and at the same time the tip of the 'master'), then having a fix on top of the 'master' like in your first solution is perfectly fine -- it is in line with how topic branches in my repository gets fixed and how the fix is propagated to 'next' and then eventually to 'master'. On the other hand, if your commits between B and the tip of your master contain enhancements and fixes to random issues (iow, it is not a degenerated merge ...
As always, thank you for the detailed response. I appreciate the
thought that goes into answering these questions that flit into my
The above method is almost a necessity when using git. If the bug fix
is committed to master, there is no way to apply that same commit to
I've noticed flows like that when looking at git history. I always
think that it demonstrates the power of git's strong-on-branches stance
because you can almost feel the story of the development without having
to read any of the commits themselves. I wonder if other DVCSs
What is your preference when, for example, you have already merged a
topic to next but then a bug fix appears?
* -- * -- * -- M -- F * -- * -- * -- M -- m (next)
/ or / /
B -- * -- * B -- * -- * -- F (topic)
F is certainly most appropriate to be on the topic branch, but we create
I'm not sure I've understood what you mean here. Which "latter" are you
talking about - you've said that you find the latter inconsistent but
It's not so much a matter of it buying you something, it is more that
when you find that bug fix commit in history you can see, by following
the fix-branch back to its source, all the revisions that contained
that bug at a glance; if you just commit on the end, you have to do the
digging yourself, and hope that someone mentioned in the commit message
which commit introduced the bug that that commit fixes.
The fact that git makes it so easy to branch and merge from a previous
point is the thing that even makes this a possibility. Perhaps I'm
spoilt now :-)
Andy
--
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
-
Look at the history of the next branch; the diagram on the right is exactly what Junio does. When topic finally graduates to master, only F is merged to master, making master's own history not show that "verbose extra merge" m. Or M really for that matter, as master gets its own M'. -- Shawn. -
I prefer just letting history show what happened, rather than try to get too smart about it ;-) -- and use branches and merges for experimental or feature work. Once a feature or experimental branch is merged into master, further work happens on master (unless there are other reasons for it to be maintained). Bugfixes are part of the life of the maint and master branches. Imagine your "option 2" being used to maintain git's maint branch. Some bugs live in the code for 6 months. The merge graph would be unreadable... and generally the project history would be really hard to make sense of. Most "special" practices around branches kind-of work in the minimalistic case, but break down badly in real-life sized projects... cheers, martin -
The big advantage of the later is, that if you have:
* -- B -- * -- * -- M1
\
-- * -- * -- M2
You can merge the fix done on yet another branch into how many branches you
need, so:
* -- B -- * -- * ----- M1
\ /
-- * -- * ----/- M2
\ / /
----------F---
If you had the fix on one of the branches, you could only cherry-pick it to
the other, but the history would not really reflect that.
--=20
Jan 'Bulb' Hudec <bulb@ucw.cz>
