Git — Workflows
Git workflows are conventions for how a team uses Git to develop software. They define how branches are created, when code is merged, and how releases are managed. The “best” workflow depends on your team size, release frequency, and project complexity.
This is the simplest workflow and resembles traditional version control systems.
main
|
+-- Commit
|
+-- Commit
|
+-- CommitEveryone commits directly to a single “main” branch. Very easy to learn, no branching, good for solo projects and Git beginners. Collaboration with others on small projects will increase merge conflicts.
Commands
A branch is just a label pointing to a commit. A worktree is an additional checkout directory linked to the same repo. You always need a branch (or commit) inside a worktree — but the worktree is what lets you see it on disk simultaneously with other branches.
| Branch | Worktree | |
|---|---|---|
| Working directories | 1 at a time | Many |
.git directory |
One per clone | Shared across all worktrees |
| Uncommitted changes | Must stash/commit before switching | Each worktree has its own state |
| Disk usage | — | Extra working tree files |
| Typical use | Linear workflow | Parallel, multi-branch work |
branch
Managing branches locally
Used to create, list, rename, and delete local branches (references to commits). It doesn’t switch branches itself—that’s git checkout or git switch. Commits made on branch currently “checked out”, git status shows checked out branch
List branches…
# list branches in repository (* marks the current branch)
git branch
# list available emote branches
git branch -r
# list available local and remote branches
git branch -aCreate and check out a branch…
# create a new branch
git branch $name
# create new branch at commit (defaults to HEAD), and switch to it
git checkout -b $branch [$commit]
# switch to branch (update HEAD, index, and working tree)
git checkout $branch
# checkout remote branch
git checkout -b $branch $remote/$branchDeleting a branch…
| Option | Description |
|---|---|
-d |
Only deletes the branch if fully merged in its upstream branch |
-D |
Deletes the branch irrespective of its merged status |
# delete branch
git branch -d $branch
# delete local copy of a remote branch
git branch -dr $remote/$branch
# delete remote branch...
git push $remote -d $branchworktree
Checking out multiple branches simultaneously
Link additional directories (worktrees) to the same repository, each checked out at a different branch.
Important constraints:
- A branch can only be checked out in one worktree at a time
- The
<path>must be outside the original repo’s tree - All worktrees share commit history, refs, stash, hooks, etc. (only the working files differ)
# Create a new branch "hotfix" and open it in a sibling directory
git worktree add ../site-hotfix -b hotfix
# Open an existing branch in a new directory
git worktree add ~/tmp/debug debug-branchFeature Branch
Branch-based workflows1 are widely used. Every new feature or bug fix gets its own branch.
- Branch — Create a dedicated branch to keeps work isolated from main.
- Commit — Small, logical commits… represent a complete, reversible change.
- Push — Share your branch with the remote for backup and visibility.
- Review — Open a merge request. Collaborators leave feedback.
- Integrate — Once approved, merge or rebase into the main branch.
- Clean up — Delete merged branches locally and remotely.
# create and switch to a new branch
git checkout -b $branch
# stage and commit changes
git add $files
git commit -m 'describe the change'
# push branch to remote
git push -u origin $branchOpen a pull request or merge request through the platform’s web interface. The review, approval, and merge steps happen there — no command-line interaction needed.
Rebase
If you have an open merge request (MR) from your branch into main, rebasing your branch onto the updated main is a common way to keep the MR current. In a personal feature branch rebasing is usually fine because you own the branch history. When you rebase, Git rewrites the commits on your branch, but nobody else is depending on those exact commit IDs.
git fetch origin # in the main branch
git checkout your-branch
git rebase origin/mainA normal push fails because Git sees that the histories are different.
git push --force-with-lease origin your-branchExisting MR should update automatically because it points to the same branch. The diff will be recalculated against the newer main.
Many teams use this workflow because the MR stays clean:
- No unnecessary merge commits
- Conflicts are handled by the author
- Reviewers see a focused change set
- The final history is easier to read
Merge
If you want to avoid rewriting history:
git checkout your-branch
git fetch origin
git merge origin/main
git push origin your-branchThis creates a merge commit but does not require a force push.
Footnotes
GitHub flow, GitHub Docs
https://docs.github.com/en/get-started/using-github/github-flow↩︎