Skip to content

Collaboration Workflows

Siddhartha Kasivajhula edited this page Apr 26, 2024 · 14 revisions

There are many things you could do to make collaboration with other developers more convenient. This page documents some options and conventions.

Sharing Work in Progress

When you're working on a contribution to the Qi code, create a draft PR as early as possible. This allows other Qi developers to see what you're working on at any time in a convenient format for discussion, showing diffs and allowing comments and discussion in context. This can be done even if your work is at a very early stage. Once the work is ready, mark the PR as "ready for review" and it can be considered for merging after that point.

Merging and Rebasing

Generally speaking, we rebase away from main, and merge towards main. For instance, feature branches (especially big ones) are typically rebased onto main to get the latest changes on main prior to merging them. This ensures that:

  1. The feature branch will represent the proposed state of the main branch and any would-be issues would be noticed prior to the merge.
  2. It avoids gratuitous complexity in the commit history (three-way merges, etc.) by ensuring that merging only happens in one direction (i.e. towards main).

Using an Integration Branch

When collaborating on a set of changes, or if the changes are backwards incompatible, it's a good idea to start an integration branch.

An integration branch is a branch created on the main drym-org Qi repo. That is, the branch should exist on the drym-org account rather than on your individual account. This allows PRs to be visible in the same way as they would be if they were done against the main branch, and in all respects makes it very similar to working on main. Such branches can function as the "development branch" on large collaborations like the Qi 4 release that included the optimizing compiler.

Rebasing an Integration Branch

For a large integration branch, it's a good idea to periodically rebase it onto main to minimize conflicts and complexity on the final rebase. This should be done with care, as any in-flight PRs against the integration branch would then not be mergable (without their being rebased). To avoid these issues, these periodic rebases should be done at points when all in-flight work has been integrated into the branch, and collaborators should be notified prior to doing the rebase in case they have any WIP branches that they haven't publicly shared. Integration branches are typically maintained on the drym-org fork rather than a personal fork. If this "remote" is called upstream in your config, you could use the following recipe:

# Make sure you have all the latest changes
$ git fetch upstream

# Create a backup, just in case
$ git checkout -b bak-<integration-branch>-<date>

# Change back to the integration branch
$ git checkout <integration-branch>

# Rebase
$ git rebase upstream/main

# Force-push changes upstream
$ git push --force-with-lease upstream/<integration-branch>

Rebasing a Stale Development Branch

Onto Main

For small PRs, simply merging them into main is generally fine. But rebasing is recommended especially for large PRs (see above), and in these cases, git rebase main (after ensuring main is up to date) should suffice (or follow the more detailed recipe above). Of course, you may need to resolve any conflicts.

Onto an Integration Branch

When you're working on a feature against an integration branch rather than the main branch, it may happen that the integration branch is rebased to main (per the recommendation above for large PRs). In this case, you would not be able to merge your changes into the integration branch as the commit hashes on your branch would not match those on the integration branch at all, preventing Git from seeing that your branch was originally based on the integration branch. You would not even be able to git rebase <integration-branch> because Git essentially thinks that your branch is a completely independent branch based on main that happens to have many commits with identical changes as the integration branch! As a result, attempting this is likely to report strange conflicts that don't make sense.

Ideally this situation should be avoided, by only rebasing the integration branch when there are no in-flight development branches (as recommended above). But if you do find yourself in this situation, then fear not! All you need to do is git rebase -i <integration-branch> (interactive rebase) and delete all commits that aren't specifically the ones you worked on in your development branch (i.e. delete all commits that are already on the integration branch, retaining only the ones you care about for your feature branch), and execute the rebase. That should go smoothly and you will then be in a position to merge your work, as you were before.

Git Remotes For Each Collaborator

In your local repo,

$ git remote add <them> git@github.com:<their_username>/qi.git

... where "them" is any convenient alias you'd like to use to refer to your new friend, the other developer.

Now you can always:

$ git fetch <them>

to try out their latest changes. If you want to make local changes or contribute to their branch, you could use:

$ git checkout -b <local_branch_name> <them>/<branch_name>
Clone this wiki locally