[U-Boot] U-Boot git usage model

Stephen Warren
2012-10-09T23:04:06Z

On 10/09/2012 04:19 PM, Albert ARIBAUD wrote:
> Hi Tom,
>
> On Tue, 9 Oct 2012 14:32:08 -0700, Tom Rini <trini@ti.com> wrote:
>
>> On Tue, Oct 09, 2012 at 03:03:28PM -0600, Stephen Warren wrote:
>>> On 10/09/2012 08:23 AM, Tom Rini wrote:
>>>> On Sun, Oct 07, 2012 at 08:49:00PM +0200, Marek Vasut wrote:
>>>>
>>>>> NOTE: I get a few more size issues with ELDK 4.2 on IXP (that
>>>>> big-endian ARM) after this patchset is applied. I wonder if we
>>>>> shouldn't just throw these away, since they're dead code mostly.
>>>>>
>>>>> The following changes since commit
>>>>> c7ee66a8222660b565e9240775efa4c82cb348c2:
>>>>>
>>>>> Merge branch 'next' of git://www.denx.de/git/u-boot-ppc4xx into
>>>>> next (2012-10-02 10:16:40 -0700)
>>>>>
>>>>> are available in the git repository at:
>>>>>
>>>>>
>>>>> git://git.denx.de/u-boot-usb.git next
>>>>>
>>>>> for you to fetch changes up to
>>>>> f0ede0e8305bc3c959862446bce40cb028b36293:
>>>>>
>>>>> usb.h: Add udc_disconnect prototype to usb.h (2012-10-07 02:08:48
>>>>> +0200)
>>>>
>>>> I had to rebase this locally to merge (such is next), and now it's
>>>> applied to u-boot/next, thanks!
>>>
>>> Hmm. Can't "git merge" solve merge conflicts just as well as "git rebase"?
>>>
>>> The problem with rebasing when pulling is that git commit IDs change,
>>> so it's much more difficult to determine when a commit is merged into
>>> a parent tree; one has to search by commit subject rather than just
>>> executing e.g. git branch -a --contains XXX. I thought Albert just
>>> agreed to use merges rather than rebases for u-boot-arm for this and
>>> perhaps other reasons.
>>
>> The short answer is that right now, u-boot/next follows the linux-next
>> model and we rebase as needed.
>>
>>> It would be awesome if U-Boot could adopt something more similar to
>>> the Linux kernel's git usage model, namely:
>>>
>>> * All downstream branches are based off some known stable point in the
>>> master branch (e.g. 2012.10-rc1). Before these branches are merged
>>> into any other branch, they can be rebased if absolutely needed, but
>>> preferably not.
>>>
>>> * Once a downstream branch is merged upwards, the downstream branch
>>> doesn't merge upstream back down into the downstream branch, but either:
>>>
>>> a) Keeps adding to the existing branch so that incremental pull
>>> requests can be sent.
>>>
>>> Or often when u-boot/master has made a complete new release does:
>>>
>>> b) Creates a new branch based on the latest rc or release from
>>> u-boot/master.
>>>
>>> (in practice, downstream branches typically end up with something like
>>> for-3.5 based on v3.4-rcN, for-3.6 based on v3.5-rcN, for-3.7 based on
>>> v3.6-rcN, some running in parallel containing either important
>>> bugfixes for the release or new development as determined by the
>>> current state of the various releases in the mainline tree).
>>>
>>> * When a branch is merged from a repo to a parent repo, it's always a
>>> git merge --no-ff; never a rebase or fast-forward.
>>>
>>> * In order to resolve merge conflicts/dependencies between different
>>> downstream branches, one of the following happens:
>>>
>>> 1)
>>>
>>> a) The first downstream branch gets merged into u-boot/master.
>>> b) The second downstream branch creates a new branch starting at an an
>>> rc or release in u-boot-master that contains it the required patches.
>>> c) The dependent patches are applied to the second downstream branch.
>>> d) The second downstream branch gets merged into u-boot/master.
>>>
>>> 2)
>>>
>>> All the patches that would usually be merged through downstream branch
>>> 2 actually get ack'd by the maintainer of downstream branch 2 and
>>> applied to downstream branch 1 after the patches they depend on. This
>>> is simplest, but may cause complications if both branches need to take
>>> patches that build on the merged patches they're merged into an rc or
>>> release in u-boot/master.
>>>
>>> 3)
>>>
>>> A topic branch is created by one of the downstream maintainers,
>>> branched from a u-boot/master rc or release, and containing just the
>>> patches that other patches depend on, and this topic branch gets
>>> merged into both the two downstream branches for further work.
>>>
>>> Yes, this does all take a little bit more thought, planning, and
>>> co-ordination, but I think having a simpler and more stable git
>>> history is worth it.
>>
>> Interesting. As this is more work on the custodians end, what does
>> everyone else say?
>
> IIUC the current rule for U-Boot is that master branches do not rebase
> while next branches can (as Tom said).
>
> Apart from this, I'm not sure why forbidding fast-forward is a good
> thing, but if there are benefits, why not.

It provides documentation in the git history of when merges were made,
and what the source of the merge was (at least using the remote name
that the merger has configured, which is better than nothing).

Related, not rebasing when merging a branch into upstream makes
validating Signed-off-by a lot easier; when a patch is directly applied,
it should be Signed-off-by the person who applied it. When a person does
a rebase rather than a merge, the git committer for the commits is
re-written as if the person doing the rebase applied the patch. Instead
when merging (and disallowing fast-forward) a merge commit is always
created so it's obvious where S-o-b should be applied (direct patch
application) and where not (to commits that are merged).

> Re merging from upstream back into downstream branches, I tend to think
> that must be allowed considering custodian trees are supposed to be
> useable, and as such may need to merge back from mainline.

Why is that required for downstream trees to be usable? What is the
definition of "usable" you're using?

Say 2012.10 is released. We assume that is usable.

Now, someone creates some ARM patches for the next release. As ARM
maintainer you do e.g.:

git checkout -b for-201304 v2012.10
git am ...

Now, there's a branch with a bunch of ARM patches applied. Presumably
none of those patches are supposed to break anything, and hence this
branch is also still usable?

Perhaps the issue is that say a new SoC or feature is added, and some of
the patches go through the ARM tree, and some drivers through the USB,
I2C, video, ... trees. In that case, in order to use all of those
features at once, somebody might have to:

git checkout -b tmp v2012.10
git merge u-boot-arm/next
git merge u-boot-i2c/next
...

This requirement is I think one of the main reasons that linux-next
exists; to provide a place where all features can be tested at once
after having been integrated together. linux-next also allows early
detection of merge conflicts that will happen when u-boot-*/next are
sent to the maintainer of u-boot/master to be merged.

Now, perhaps you're thinking that in this scenario that u-boot-arm/next
can simply merge in u-boot-usb/next, u-boot-i2c/next, u-boot-video/next,
etc. in order to create a fully working system. But, wouldn't it be
better if all those merges happened only in u-boot.git in a co-ordinated
fashion once? After all, perhaps the I2C maintainer also wants his/her
branch to be usable on that new platform, and does the reverse merges.
Then you end up with spaghetti and unparsable merge history.

> And I am pretty sure we don't need to create branches "for such
> version" "based on such version" all the time; keeping each custodian
> master current enough should suffice IMO.

Well, we already have this, it's just that the branch names are re-used
in a rolling fashion rather than having static names for each release.

While v2012.10 is the next release, u-boot-arm/master is for-v2012.10
and u-boot-arm/next is for-v2013.xx. Then, when v2012.10 is release,
doesn't u-boot-arm/master become for-v2013.xx and u-boot-arm/next become
for-v2013.yy.