[PATCH] Use git pull with rebase in build script

Dirk Hohndel dirk at hohndel.org
Wed Aug 26 11:23:52 PDT 2015


On Sun, Jul 12, 2015 at 12:20:57PM -0700, Linus Torvalds wrote:
> On Sun, Jul 12, 2015 at 11:07 AM, Dirk Hohndel <dirk at hohndel.org> wrote:
> >
> > It's just that I don't know how else to do it and keep the branches
> > reasonably useful.
> 
> So I guess the current model *works*, it just causes nasty problems
> occasionally.
> 
> The best model is likely one where you have two separate branches:
> 
>  - you have the "ugly working branch" that is never ever rebased, and
> that people who want to track libdivecomputer as a _user_ would be (so
> this is what the build.sh script would pull).
> 
>    Because it's never rebased, "git pull" works fine, with or without
> rebase (and with "--rebase" might be better, because *if* somebody has
> their own work going on, they most definitely wouldn't want to have
> that work ever get mixed into that branch.
> 
>  - you have the "cleanup" branch, which ends up occasionally rebasing
> on top of upstream libdivecomputer, and has a clean history that you
> can hope that Jef will eventually take more and more of.
> 
>   This "cleanup" branch you don't necessarily work on very actively,
> it's more of a "update when libdivecomputer has done something we
> really want or care about".
> 
> Now, that all sounds easy ("just have two branches"), but the magic is
> that you want to keep them in sync. And *that* is fairly simple, but
> it's simple only if you follow a few basic rules.

OK, I have tried to implement this. Let's see if I manage to keep it up
without going insane. But I really like the ideas that Linus explained
here and I think that this will make it easier for Jef or for any distro
that would like to take our patches.

So we now have (in git://git.subsurface-divelog.org/libdc) two new
branches that right now are identical:

Subsurface-branch (this will be the 'ugly working branch')
Subsurface-clean  (this will be the 'cleanup branch')

As Linus explains, I plan to keep Subsurface-branch as a branch one can
continue to pull from without going insane. So moving forward THIS is what
developers should use. I'll update the build.sh accordingly.

And Subsurface-clean will continue as a clean branch on top of
libdivecomputer master. So this one will rebase every once in a while.
It's NOT the branch people should use to build, it's the branch that
distros can use to get our patches relative to a recent libdivecomputer
master, and where Jef can easily see which patches we have on top of his
master right now.

>  (a) they start out with the exact same contents (you're a
> mathematician, this is going to be an inductive proof, and this is the
> starting point - and the trivial case is by having the exact same tree
> with the same history).

That's what I have. Same tree, same history.

>  (b) You need to remember this place in the ugly working tree.  The
> *contents* are the same, but the history may not be, remember, so you
> might tag that location with "sync-point" or something like that.

Done (I haven't pushed those tags... since they will move over time and
since only I should have a need for them)

>  (c) when *you* do libdivecomputer development, you probably want to
> work in the ugly working tree, and you just keep adding commits to it.
> Ignore the cleanup tree, it's not what people really *use*, it's more
> of a nice marker of what used to be clean development ready for
> merging back upstream. So work work work in this tree normally, and
> the two trees diverge both in history and in content. But the clean
> tree stays the same.
> 
>  (d) you decide that you want to synchronize the two trees after
> having done *your* work, you can now do a complex rebase
> 
>         git rebase -i --onto cleanup sync-point
> 
>       which should rebase all your work you did in (c) since your last
> sync-point onto the cleanup branch.
> 
>      NOTE! It's important that "cleanup" and "sync-point" have the
> exact same tree: that guarantees that the rebase will be trivial.
> You're applying the same patches onto the same tree state - it's just
> a different history. You're now moving your ugly tree work to be on
> top of the cleaned-up history.
> 
>  (e) you may choose to clean up history further now (it maybe you
> weren't so careful when you were working in your ugly tree, but now
> you want things to be tip-top, so you do some cleanup and further
> testing in this state, wanting to make it be something that you could
> send upstream to Jef.
> 
>  (f) in fact, it's now so nice and clean that you update the "cleanup"
> branch with the new state:
> 
>         git branch -f cleanup HEAD
> 
>      because you now have a new cleanup state.
> 
>  (g) but now you've rebased your ugly tree, and it might not even
> match the old state of your working tree because of the cleanups you
> did in (e), so we've really screwed up! The whole point was to make
> the ugly tree always be a fast-forward! And the whole point was to
> keep the two in sync (see step (a))! What kind of idiotic working
> model is this!
> 
>  (h) to the rescue. At this point, you just do "git pull --strategy
> ours <publicrepo>" to say "pull in all the stuff I've pushed out, but
> use the merge strategy of picking the exact current state".
> 
>      This is what makes your tree the "ugly tree": you just created a
> nice clean branch (to use as your cleaned-up version), and then you
> use the state of that branch (to make sure it matches the cleanup -
> see point (a)), but you merged in all the ugly history, including all
> the old ugly merges, so that your branch is always a fast-forward.
> 
>  (i) Now remember this state as the new "sync-point":
> 
>         git tag -f sync-point
> 
>      (or I guess you could keep "sync-point" as just a branch instead
> of a tag, that way you'll have the branch history in the reflog)
> 
> And now we're back to (a).

And this is what I plan to do from now on. Let's see how it works out :-)

> What I didn't describe above is what you should do when you actually
> want to update from Jef's upstream. When you do that, make sure that
> you synchronize like the above first, so that your clean branch and
> your ugly branch have the same contents. Then you just check out your
> clean branch, and rebase it on top of its upstream (ie Jef's branch).
> The clean branch you rebase, after all, and it has simple clean
> history so rebasing it on top of Jef's should be fairly simple too,
> and keeps the history clean:
> 
>         git checkout cleanup
>         gti pull --rebase
> 
> And after you've rebased the clean branch, you go back to your ugly
> branch, and since the clean and ugly started out the same, you just
> want to take the new clean base:
> 
>         git checkout ugly
>         git merge --strategy theirs cleanup
> 
> which merges the new cleanup state into your ugly branch and uses the
> tree from that clear version. So now the two trees have the same
> contents, and your ugly branch is a fast-forward and has all the
> changes from Jef's tree. And since the two trees now match again, you
> do
> 
>         git tag -f sync-point
> 
> again to show that you've synced.
> 
> The above sounds really complicated, but it's not really. I just wrote
> it out in really small steps to make everything clear. And notice that
> (c) is the only *normal* thing. The whole "keep in sync" thing is
> something you migth do every month or two. You want to minimize the
> crazy merges, just to make sure your ugly branch isn't *too* damn
> ugly. So all the sync-point stuff is stuff that you do very seldom,
> and notice how all the steps are designed to never have any conflicts
> or anything like that in them, because the base trees were all the
> same (ie the only place you can get conflicts is when you do the
> rebase to get Jef's code - that's inevitable - or when you decide to
> do the cleanup in (e), but that's all your own commits that you're
> just cleaning up, so that's purely a matter of how much cleanup you
> want to do and how painful you want to make it).

This I think I'll do more often than the first set of steps. We go through
bouts of activity when we add something to both libdivecomputer and
Subsurface, but in general Jef tends to do steady improvements to
libdivecomputer and I want to make sure we keep pulling them in on a
regular schedule.

Thanks Linus for the detailed explanation. I think this will make the
experience better both for developers building Subsurface and for Jef /
any distributions who want to package Subsurface after all :-)

/D


More information about the subsurface mailing list