On Saturday 2007, February 03 06:40, Junio C Hamano wrote: > Also, don't use "git reset" on a publicly-visible branch that > other developers pull from, as git will be confused by history > that disappears in this way. > > I do not think this is a good explanation. For example, if we > do this: I agree it's not a good explanation, I think it is good policy though. I love an oppourtunity to blather on and your post has given it to me :-) I'm sure I'll be preaching to the converted though. In the following I've assumed that both "h" and "a" commits are independent work, neither of which works on "j" (which isn't quite what you described). It's not really appropriate for the tutorial, so I haven't really helped you. ----------------- git's easy manipulation of branches encourages one to try to make history really tell the story of development. It's more than just recording snapshots, there is information in the history itself - reasons for decisions can be recorded - separating and collecting commits into appropriate branches instead of one giant linear block. As you say git is perfectly okay with the rewound branch and will do the Right Thing to preserve the changes. However, it won't get the spirit of the changes right. > (4) Alice pulls from me again: > > ---o---o---o---j---a---a---* > \ / > h---h---h---h > > Contrary to the description, git will happily have Alice merge > between the two branches, and never gets confused. The problem is not that the working tree is wrong, it is that the history is wrong. This sequence of development isn't best represented by a merge. When we look at the history later, we'll see it as two branches, but that isn't true. The graph shows that "j" was committed and then probably conflicted in "*" and fixed. The problem is that you can't point to any non-merge commit that reverted/corrected "j" and explains why that wasn't a good idea - so the "story" that the history tells us is incomplete. The correction was done just as a conflict resolution in "*". Any of these would be correct: 1) "h" and "a" are parallel; "j" never happens ---o---o---o----a-----a----* \ / h---h---h---h 2) Alice corrects "j" with a "!j" revision - "!j" would then describe why "j" was wrong and what the fix was. "h" would have to have nothing to do with the "j" topic in this case. ---o---o---o---j---!j---a---a---* \ / h-----h-----h----h Of course, both of these require information from the developer. (1) can't be done after the push has been done (because "j" is already "out there") and (2) requires that "h" know that Alice has fixed the problem and the Alice knows that the "j" problem needs fixing (and probably doesn't belong in Alice's branch anyway). The only solution that keeps the history integrity, is the one that all the git manuals reccommend. 3) Don't rebase at all, correct the problem and record the correction. --o---o---o---j------a------a------* \ / !j---h---h---h---h That is - once a mistaken commit has been pushed out, it's there forever, accept that and don't rebase to before the last push. Sometimes it makes the history less pretty, but it makes it more right. Without "!j", no one would ever know what was wrong with "j". In short - heed the warnings - you will get much better history if you don't rebase branches that have already been pushed upstream. ----------------------- How about that as the explanation for the tutorial? What do you mean I haven't simplified anything and have replaced one paragraph with a page worth of overly wordy ravings? HOW DARE YOU! :-) Andy -- Dr Andrew Parkins, M Eng (Hons), AMIEE andyparkins@xxxxxxxxx - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html