Skip to content

Git Workflow

Cyrus Omar edited this page Jun 26, 2023 · 18 revisions

The Hazel codebase is often undergoing multiple concurrent large refactorings. To mitigate the pain of large merge conflicts, we adopt a Git workflow of feature branches combined with frequent merges from and into dev, our central development branch. Frequent synchronization with dev will help keep other contributors up-to-date on your code changes that may overlap or unintentionally interact with theirs (unavoidable given how large each refactoring is) and help minimize wasted effort due to outdated assumptions (e.g. someone writes a ton of code using a datatype that you had refactored but not yet merged into dev).

This system requires some discipline in order to work reasonably. You should aim to synchronize your branch with dev not only frequently, but also such that dev can always build with no regressions in functionality. Your feature does not need to be complete to be merged into dev. The only exception here are starter projects, which we will generally only merge into dev when complete. However, you should keep your starter project branch up to date with changes in dev as soon as they occur.

Starting a project

Create a new branch off of dev with your project name all lowercase (Git on Windows/Mac doesn't deal well with uppercase). Push your branch to GitHub and open a pull request (PR) from your branch into dev. The pull request provides a convenient place for other contributors to monitor and provide early feedback on your code. You should mark the PR as draft (in the right sidebar under the list of possible reviewers), and when it is ready for review you can click the Ready for review button at the bottom of the PR page.

The PR will update automatically as you push to your branch, so you don't need to wait until the PR is ready before creating it!

If you are working on something for which there is a corresponding issue, you can link the PR to the issue from the right sidebar. Generally, the Issue tracker should be used for discussing the issue abstractly, and the PR can be used for all discussion related to the solution approach. When in doubt, use the PR for discussion.

When you get back to work

Pull the latest changes on dev from GitHub and merge them into your branch. Prioritize resolving merge conflicts.

git checkout dev
git pull
git checkout <your branch>
git merge dev

Do not rebase onto dev -- rebasing deletes your existing commits and replaces them with new ones, which screws with any existing feedback on your pull request.

Before you commit to your branch

Make sure you have followed the Code Style Guide. Also make sure you have run make dev such that no reformatting is needed (any remaining autoformatting will break the GitHub Actions build).

After you commit to your branch

Consider whether you could merge your latest changes into dev. If not, prioritize getting your branch into a state suitable for merging into dev.

It's easy to let merges into dev blow up in size in the name of preserving build and functionality. Mitigation strategies include:

  • If you discover in the course of implementing your feature that you need to perform a supporting but inessential refactor to some existing datatype or signature
    1. stash your current changes that depend on the refactor
    2. perform the refactor, commit and merge to dev
    3. unstash your changes and proceed
  • If you are add a new variant to a datatype and it will take a long time to finish the refactoring, first commit and merge to dev a set of changes that adds the variant to all relevant case expressions with failwith("unimplemented") before you begin to commit any actual implementation.
  • If you are aware that your changes may lead to difficult-to-resolve merge conflicts with the changes of another contributor, reach out to that person directly and communicate about how you may better synchronize your work.
  • Comment out code that doesn't work (only if the other strategies aren't suitable).

Additional References