1

I'm trying to incorporate a community maintained patch on OpenSSH (Roumen Petrov's X.509v3 implementation) along with our own patches. This does not fit regular solutions as far as I know, as this patch is huge and all releases of this patch are very much bound to a specific upstream version of OpenSSH. The obvious upgrade of OpenSSH on top of the patched version is a plain merge conflict and exactly what I want to avoid, yet keeping the upstream and patched version distinct in Git.

Right now, I have done this in Git using branches:

master
gert/develop
vendor/orig
vendor/roumenpetrov

With

  • vendor/orig being a plain, original OpenSSH branch of code with every commit one of the OpenSSH release versions, also tagged, e.g. 5.9p1
  • vendor/roumenpetrov being a branch forked from vendor/orig with the corresponding patch applied, also tagged, e.g. 5.9p1+x509-7.1
  • gert/develop being the "daily development" branch, based off the vendor/roumenpetrov, now with a few local low-impact commits.
  • master being the branch for release-ready code

My goals are basically this:

  • Detectability of all changes in code. E.g. "Are we on 6.0p1 already in master?" -> git branch --contains <commit-of-openssh-6.0p1> yes/no answer.
  • Easy upgrade of both OpenSSH as well as the patches from Roumen, with the least effort on conflicts with the local patches.
  • View upgrades new versions as single commits: e.g. "Upgrade to patch to X509-7.4" along with "Upgrade to new upstream 6.0p1".

Practically I have an issue with the model above. Suppose I want to upgrade to 6.0p1 along with the corresponding new 7.4 patch from Roumen. What should I do? I found the following options:

  • upgrade, revert, upgrade, merge

    1. In vendor/orig, upgrade the OpenSSH version.
    2. In vendor/roumenpetrov, revert the previous commit (git revert 12345678, the 7.1 patch).
    3. In vendor/roumenpetrov, merge with vendor/orig.
    4. In vendor/roumenpetrov, apply the new patch and commit.
    5. In gert/develop, merge with vendor/roumenpetrov

    Problems: 1) a lot of actions to take, 2) The revert action is a separate commit confusing when reading the log ("6.0p1 release" -> "revert X509 7.1" -> "merge vendor/orig" -> "apply X509 7.4".), 3) the revert with subsequent re-patch actions could cause more than ideal probability of conflicts, right?

    Plus side: git log vendor/orig..vendor/roumenpetrov shows me actual changes, although listing four commits.

  • same, but with --no-commit

    1. In vendor/roumenpetrov: git revert -n <patch-7.1>
    2. In vendor/roumenpetrov: git cherry-pick -n <openssh-6.0p1>
    3. In vendor/roumenpetrov: git commit magically recognizes this as the the same commit as from the message.

    Problem: git log vendor/roumenpetrov..vendor/orig shows openssh-6.0p1 not being applied because it has a different commit hash (diff=empty).

  • merge --squash

    Problem: same as above, but for another reason.

  • rebase

    Problem: we push this repository to a central (not-yet-public) location. Rebasing in the vendor/roumenpetrov branch on a newer vendor/orig is therefore not an option as far as I know if other people are working on this branch as well. This also holds for the other remote branches. See this answer as for why I believe rebasing is not an option for my case.

    And, is it true what svnpenn mentions?

    without a rebase you have no other choice than to do ugly merge commits.


So, taking a step back, what is my best option here to have this maintainable? Do I have to take sacrifices for the inevitable reason being the patch from Roumen depending on a specific OpenSSH version? Do I have to revise this whole branching model? Or am I missing out on something very basic?

Community
  • 1
  • 1
gertvdijk
  • 24,056
  • 6
  • 41
  • 67

1 Answers1

1

The obvious upgrade of OpenSSH on top of the patched version is a plain merge conflict and exactly what I want to avoid, yet keeping the upstream and patched version distinct in Git.

The way I handle this is by keeping the changes on a separate branch

A--B--C
       \
        X--Y--Z

then if commits are made upstream

A--B--C--D--E--F
       \
        X--Y--Z

you can rebase the branch onto the new HEAD

 A--B--C--D--E--F
                 \
                  X'--Y'--Z'

this avoids merge commits, and will make it very easy to merge into master should the upstream people ever decide to do so.

ref

Zombo
  • 1
  • 62
  • 391
  • 407
  • 1
    Yes, I know I can rebase, but that's not valid if I want to **push** this branch out. See [this answer](http://stackoverflow.com/a/2219681/1254292). So, this is not an answer to my question I believe. – gertvdijk Jan 29 '13 at 23:29