Open source

Sefism.

Chapter 02

Git and GitHub for contributors

Working in a repository you do not own: forks, branches, keeping in sync with upstream, rebasing and readable commits.

Fork

What
Your own copy of someone else's repository on GitHub, where you can push branches without write access to the original.
Why
It is how outside contributors propose changes: push to your fork, then open a pull request into the original project.
Shell
gh repo fork owner/project --clone
cd project
git remote -v

Origin and upstream

What
Conventional remote names: origin points to your fork, upstream points to the original project you forked from.
Why
You pull the latest changes from upstream and push your branches to origin. Mixing them up is a common source of confusion.
Shell
git remote add upstream \
  https://github.com/owner/project.git
git fetch upstream

Feature branch

What
A short-lived branch created from the latest upstream main for one change, named after what it does.
Why
One branch per pull request keeps changes separate, so you can work on several at once and your fork's main stays clean.
Shell
git switch main
git pull upstream main
git switch -c fix/parse-empty-config

Watch out

Committing directly to your fork's main branch, which makes later pull requests carry unrelated commits.

Keeping a fork in sync

Also called Sync fork

What
Bringing new commits from upstream into your fork and branches, by fetching upstream and rebasing or merging.
Why
Projects move fast. Branches based on old code conflict more and may fail CI against the current main.
Shell
git fetch upstream
git switch main
git merge --ff-only upstream/main
git push origin main

Rebase

Also called rebasing

What
Replaying your branch's commits on top of a newer base, such as the latest upstream main, which rewrites their history.
Why
It keeps a linear history and resolves conflicts in your branch before review. Many projects ask contributors to rebase rather than merge main in.
Shell
git fetch upstream
git rebase upstream/main
git status
git add path/to/resolved-file
git rebase --continue

Watch out

Rebasing a branch other people have based work on, which rewrites history under them.

Merge conflict

What
When Git cannot combine changes automatically because two commits edited the same lines, and it marks the file for you to resolve by hand.
Why
Conflicts are normal in active projects. Resolving them carefully, then running tests, keeps your pull request mergeable.

Watch out

Accepting your own side of every conflict without reading what upstream changed.

Good commit message

Also called commit message

What
A short imperative subject line of about 50 characters, a blank line, then a body explaining what changed and why.
Why
Reviewers and future maintainers read history to understand decisions. Clear messages make review and git log useful.
Code
Fix crash when config file is empty

Loading an empty YAML file returned None and
the validator assumed a dict. Treat None as an
empty config and add a regression test.

Fixes #482

Watch out

Messages like "fix", "wip" or "changes" that tell nobody anything.

Conventional Commits

What
A commit message convention with a type prefix such as feat:, fix: or docs:, an optional scope, and BREAKING CHANGE for incompatible changes.
Why
Many projects use it to generate changelogs and decide version bumps automatically, so their CI may reject messages that do not follow it.
Example
feat(cli): add --dry-run flag, or fix(parser): handle empty config files

Squashing and force-pushing

Also called force-push, squash on merge, interactive rebase, squashing

What
Combining several commits into one, for example with interactive rebase, then updating your remote branch with a force push because history changed.
Why
Maintainers often want tidy commits. --force-with-lease refuses to overwrite the remote if it has commits you have not seen.
Shell
git rebase -i upstream/main
git push --force-with-lease origin fix/parse-empty-config

Watch out

Using plain --force, which can silently delete a maintainer's commits pushed to your branch.

Everyday Git commands

Also called everyday commands

What
The commands used constantly while contributing: status, diff, add -p, stash, log --oneline and restore.
Why
Checking what changed before each commit avoids pushing stray files, debug prints and unrelated formatting changes.
Shell
git status
git diff
git add -p
git stash push -m "wip"
git log --oneline -5
02 · Git and GitHub for contributors2 / 7