# Contributing

## Adding external contributions

The public soniclib repo does not share history with the internal one (this). So
a simple git merge is not the right approach to pulling in external changes.

Instead, you should use a rebase. Let's assume there is a customer with a fork
of our public repo called `fork`. They branched off of a commit in the public
repo `public`. And we'll call this (private) repo `origin`.

You can set up multiple remotes to track the `fork` and `public` repositories.
Use the following commands:

```
git remote add public <public repo url>
git remote add fork <fork repo url>
```

Assume the situation is as follows.

```
origin     i1---i2---i3

public     S0---S1
                 \
fork              f1---f2---f3
```

Above, the private (origin) commits are labeled with prefix `i`. The public
commits are essentially squashed versions of the private commits. These are
denoted `S`. `S1` is is the result of copy-pasting select components of the
private repo at commit `i2` and creating a new commit in the public repo. So it
is not technically a merge, and the branches do not share history.

The fork commits are denoted `f`. These exist outside of our organization. We
want to squash these and merge to our private repo. The result should be the
following:

```
private    i1---i2---i3-----I1

public     S0---S1
                 \
fork              f1---f2---f3
```

Above, `I1` is the result of squashing `f1`-`f3`. To obtain this result, the
following command can be used.

```
git rebase -i --onto i3 S1 f3
```

This can be read as "take the commits from S1 through f3 and apply them to i3".

This runs `git rebase` in interactive mode. You should get prompted to edit
the rebase todo list. Here you can choose to squash the `f` commits and change
the commit message if you like.

Next, the rebase operation will run. It may result in merge errors. These need
to be resolved by following the instructions on the command line.

After the rebase finishes successfully, you will have the newly squashed commit
added to the tip of the private repo target branch in a detached HEAD state.
From here, just create a new branch, then create a PR to merge it.

```
git checkout -b feature/external-contrib
git push origin feature/external-contrib
```

## Authorship

There are two places where external contribution authorship can be lost from the
git history. The first is when the external commits are squashed. The second is
when the private repo is pushed to public (since this is equivalent to a
squash).

Because of this, you should ensure authorship of code used from external sources
is preserved by inserting it as comments in the code. It's probably good enough
to do this on a per-file basis, i.e., list contributors at the top of the file.
You could also choose to do it on a finer scope, like functions, or even lines,
if it's more critical for some reason.
