Skip to main content

Command Palette

Search for a command to run...

How to Contribute to a Team Project Using Git and GitHub: The Complete Workflow

Updated
16 min read
How to Contribute to a Team Project Using Git and GitHub: The Complete Workflow
B
Software Engineer (Backend Engineer) | AI Engineer

Collaborative software development requires more than writing code. It also requires a shared understanding of how changes move safely from a developer’s computer into the team’s codebase.

Git and GitHub provide the tools for this process, but it is common for developers to learn individual Git commands before understanding how those commands fit into a complete team workflow. Knowing how to run git add, git commit, or git push is useful, but effective collaboration also involves branching correctly, keeping work synchronized, opening pull requests, participating in code reviews, resolving conflicts, and following the team’s merge process.

This guide connects those pieces and explains the complete contribution workflow. Whether you are joining a development team, contributing to an open-source project, or refreshing your knowledge, the goal is to help you contribute confidently, consistently, and safely.

First, Understand the Basic Flow

A normal contribution should move through these stages:

Update local repository
        ↓
Create a branch
        ↓
Make focused changes
        ↓
Review and commit the changes
        ↓
Push the branch
        ↓
Open a pull request
        ↓
Receive code review
        ↓
Pass automated checks
        ↓
Merge according to team policy
        ↓
Delete the completed branch

A pull request is not merely a request to combine code. It is a place for the team to inspect, discuss, test, improve, approve, and document a proposed change.

Why This Workflow Matters

A structured Git and GitHub workflow helps a team:

  • Prevent unfinished or unreviewed changes from entering important branches.

  • Reduce accidental overwrites and unnecessary merge conflicts.

  • Make every change traceable to a branch, commit, task, and pull request.

  • Review code for correctness, security, performance, and maintainability.

  • Revert problematic changes more easily.

  • Allow several developers to work on the same project without interfering with one another.

  • Preserve a useful history that explains how and why the codebase changed.

  • Create a consistent process for onboarding new contributors.

This has become even more important with the growth of AI-assisted software development. AI coding tools can help developers generate features, tests, migrations, documentation, and refactoring suggestions more quickly. However, code produced with AI must still be understood, inspected, tested, and reviewed before it enters a shared codebase.

Faster code generation should not mean faster unreviewed merging. Whether a contribution was written manually, suggested by an AI assistant, or produced by an automated coding agent, it should pass through the same branching, testing, review, and approval process.

A reliable Git and GitHub workflow ensures that increased development speed does not come at the expense of code quality, security, team visibility, or accountability.

Git and GitHub Are Not the Same Thing

Git is the version-control system running on your computer. It tracks changes, commits, branches, merges, and repository history.

GitHub is a collaboration platform that hosts Git repositories and provides features such as:

  • Pull requests

  • Code reviews

  • Issues

  • Actions and automated checks

  • Branch protection

  • Release management

  • Team permissions

You can use Git without GitHub, but teams commonly use them together.

Understand the Four Important Locations

When working with Git, your changes move through four important locations:

  1. Working directory: The files you are currently editing.

  2. Staging area: The changes selected for the next commit.

  3. Local repository: Commits saved on your computer.

  4. Remote repository: The shared repository hosted on GitHub.

The usual movement is:

Working directory
    git add
Staging area
    git commit
Local repository
    git push
Remote repository

Before You Start Coding

Before changing anything, check the repository for:

  • README.md

  • CONTRIBUTING.md

  • Pull request templates

  • Issue templates

  • Branch-naming rules

  • Coding standards

  • Testing instructions

  • Commit-message conventions

Do not invent your own workflow when the project already has one.

Also confirm that the task is assigned to you or that the team knows you are working on it. Two developers unknowingly solving the same problem usually create unnecessary conflicts and wasted effort.

Cloning and Understanding Remotes

Clone the repository:

git clone https://github.com/company/project.git
cd project

Inspect its remotes:

git remote -v

A remote is a saved reference to another Git repository.

The most common remote names are:

  • origin: The repository from which you cloned, or the repository to which you normally push.

  • upstream: The original repository when you are working from a fork.

For a fork-based workflow, add the original repository as upstream:

git remote add upstream https://github.com/original-owner/project.git
git remote -v

Read more about Git remotes and configuring an upstream remote.

Never Begin New Work from an Outdated Branch

Before creating a branch, update your local base branch.

git switch main
git fetch origin
git pull --ff-only origin main

If the project uses develop as its base branch, use develop instead of main.

git fetch downloads information from the remote repository without immediately changing your working branch.

git pull fetches remote changes and integrates them into your current branch.

Using --ff-only prevents Git from creating an unexpected merge commit while updating your local branch.

Always Work on a Separate Branch

Do not implement features directly on main.

Create a branch from the latest base branch:

git switch -c feature/user-profile

Common branch prefixes include:

feature/user-profile
fix/payment-validation
bugfix/login-redirect
hotfix/checkout-crash
refactor/order-service
docs/api-authentication
test/invoice-service
chore/update-dependencies

A good branch name should communicate what the branch contains.

Avoid names such as:

my-branch
new-work
changes
testing
final-fix
branch-2

The exact branching strategy depends on the team. Some teams use short-lived branches from main. Others use develop, release branches, or hotfix branches. Follow the repository’s established strategy.

Keep Each Branch Focused

A branch should solve one clearly defined problem.

Do not combine:

  • A new feature

  • An unrelated bug fix

  • File formatting

  • Dependency upgrades

  • Database changes for another task

into one branch or pull request.

Focused branches are easier to:

  • Review

  • Test

  • Merge

  • Revert

  • Understand later

Inspect Your Changes Before Committing

During development, regularly check your repository:

git status
git diff

git status shows modified, staged, untracked, and deleted files.

git diff shows changes that have not been staged.

Before committing, inspect the staged changes:

git diff --staged

This prevents accidental commits of debugging code, generated files, credentials, environment files, or unrelated modifications.

Stage Changes Deliberately

Stage specific files:

git add app/Services/PaymentService.php
git add tests/Feature/PaymentTest.php

For more control, stage individual sections:

git add -p

Avoid blindly running the following without checking what changed:

git add .

It may include files that do not belong in the commit.

Write Meaningful Commits

A commit should represent one logical change.

Bad commit messages include:

update
changes
fix
work done
final
final final
miscellaneous changes

Better commit messages include:

Add email verification to registration flow
Fix duplicate payment reference validation
Prevent suspended users from creating orders
Add tests for invoice cancellation
Refactor notification delivery service

Write commit messages in the imperative form:

Add...
Fix...
Remove...
Update...
Prevent...
Refactor...

Teams that use Conventional Commits may use this format:

feat: add email verification
fix: prevent duplicate payment references
docs: document webhook authentication
test: add invoice cancellation tests
refactor: extract notification service
chore: update development dependencies

Commit your staged changes:

git commit -m "Fix duplicate payment reference validation"

Do not create one massive commit after several days of unrelated work. Also avoid creating meaningless commits for every tiny edit. Each commit should tell a useful part of the development story.

Test Before You Push

Before sharing your branch:

  • Run the relevant tests.

  • Run the formatter or linter.

  • Check the application manually where appropriate.

  • Remove debugging statements.

  • Confirm that no secret or environment file was included.

  • Review the complete diff.

Useful commands include:

git status
git diff
git diff --staged
git log --oneline

A developer should not use the pull request reviewer as the first person to inspect their code.

Push the Branch

Push the branch and establish its remote tracking branch:

git push -u origin feature/user-profile

After the first push, future pushes can usually use:

git push

Push your feature branch, not main.

Open a Pull Request

Create a pull request from your feature branch into the correct base branch.

Confirm both sides carefully:

base: main
compare: feature/user-profile

A useful pull request should explain:

  • What changed

  • Why the change was needed

  • How it was implemented

  • How reviewers can test it

  • Screenshots or recordings for visual changes

  • Related issue or task number

  • Known limitations or follow-up work

Example:

## What changed

Added email verification to the registration process.

## Why

Unverified accounts were receiving access to protected features.

## How to test

1. Register a new account.
2. Confirm that a verification email is sent.
3. Attempt to access the dashboard before verification.
4. Verify the email address.
5. Confirm that dashboard access is granted.

Closes #142

Open a draft pull request when the work is incomplete but you want early feedback. Draft pull requests clearly indicate that the code is not ready to merge.

Read more about creating pull requests.

Review Your Own Pull Request First

Before requesting another developer’s time:

  • Read every changed file.

  • Check for accidental changes.

  • Confirm the target branch.

  • Ensure tests are passing.

  • Check the pull request description.

  • Look for repeated code, unclear names, and unfinished work.

  • Confirm that the changes satisfy the task.

A pull request should be ready for review before reviewers are invited.

Request the Right Reviewers

Request reviews from developers who understand the affected part of the system.

A reviewer should evaluate:

  • Correctness

  • Security

  • Maintainability

  • Test coverage

  • Performance

  • Architecture

  • Naming and readability

  • Possible side effects

  • Compliance with project standards

Teams can use a CODEOWNERS file to request reviews automatically from people responsible for specific files or directories.

Respond Properly to Review Comments

Code review is collaboration, not an attack.

When a reviewer requests a change:

  1. Understand the concern.

  2. Ask for clarification when necessary.

  3. Update the same branch.

  4. Commit and push the correction.

  5. Respond to the comment.

  6. Request another review when ready.

Example:

git add .
git commit -m "Address validation concerns from review"
git push

The pull request updates automatically when new commits are pushed to its branch.

Do not close a review conversation without addressing it or clearly explaining why a different approach was chosen.

Keep the Branch Up to Date

Other changes may enter main while your pull request is being reviewed.

Update your local remote information:

git fetch origin

Then update your feature branch according to the team’s preferred strategy.

Using rebase:

git switch feature/user-profile
git rebase origin/main

After rebasing a branch that has already been pushed:

git push --force-with-lease

Use --force-with-lease, not plain --force. It provides additional protection against overwriting remote work.

Using merge:

git switch feature/user-profile
git merge origin/main
git push

Do not mix merge and rebase strategies carelessly. Follow the team’s policy.

Read more about keeping a pull request in sync.

Resolve Merge Conflicts Carefully

A conflict occurs when Git cannot automatically combine competing changes.

When a conflict happens:

  1. Identify the conflicted files:
git status
  1. Open each file and look for conflict markers:
<<<<<<< HEAD
Your version
=======
Incoming version
>>>>>>> origin/main
  1. Decide what the final code should contain.

  2. Remove the conflict markers.

  3. Test the combined result.

  4. Stage the resolved files:

git add path/to/file
  1. Continue the operation.

For a rebase:

git rebase --continue

For a merge:

git commit

Do not resolve a conflict by automatically accepting “ours” or “theirs” without understanding both changes.

Do Not Merge Your Own Pull Request Without Authority

Opening a pull request does not automatically give you the right to merge it.

In a properly reviewed team workflow, a pull request should be merged only when:

  • Required reviewers have approved it.

  • Requested changes have been addressed.

  • Automated tests and checks have passed.

  • The branch is up to date where required.

  • The person responsible for merging has authorized it.

  • The repository’s merge policy has been followed.

Some teams allow authors to merge after all requirements are satisfied. Others reserve merging for maintainers, team leads, release managers, or reviewers.

The rule is simple: follow the team’s policy and never bypass the review process.

Never approve your own work merely to satisfy an approval requirement. Never use administrative privileges to bypass failed checks unless the team has explicitly authorized an exceptional procedure.

Understand the Main Merge Strategies

GitHub commonly provides three merge options.

Merge commit

Preserves all commits and adds a merge commit.

Merge pull request #142 from feature/user-profile

Squash and merge

Combines the branch’s commits into one commit before adding it to the base branch. This is useful when a branch contains many small or corrective commits.

Rebase and merge

Replays the branch’s commits on top of the base branch, producing a linear history.

No strategy is universally correct. Use the strategy selected by the project.

Clean Up After the Pull Request Is Merged

After the pull request has been merged:

git switch main
git pull --ff-only origin main
git branch -d feature/user-profile

Delete the remote branch when it is no longer needed:

git push origin --delete feature/user-profile

Do not continue adding unrelated work to an already merged branch. Create a new branch for the next task.

Syncing a Fork

When contributing through a fork:

git switch main
git fetch upstream
git merge --ff-only upstream/main
git push origin main

Your remote structure will normally be:

origin   → your fork
upstream → original repository

GitHub also provides a Sync fork option. See the official guide on syncing a fork.

Working with Unfinished Local Changes

When you need to change branches but are not ready to commit, you can temporarily store your changes:

git stash push -m "WIP: payment validation"

Restore them later:

git stash pop

View saved stashes:

git stash list

A stash is temporary storage, not a replacement for proper commits and branches.

Practices Every Team Should Prevent

Developers should not:

  • Work directly on main.

  • Push directly to a protected branch.

  • Merge unreviewed code.

  • Merge while required checks are failing.

  • Approve their own pull requests to bypass policy.

  • Force-push shared branches.

  • Commit passwords, tokens, or .env files.

  • Combine multiple unrelated tasks in one pull request.

  • ignore unresolved review comments.

  • Reformat an entire codebase during an unrelated change.

  • Commit generated or dependency files unless required.

  • Use unclear branch names and commit messages.

  • Resolve conflicts without understanding both changes.

  • Rewrite public branch history without coordinating with the team.

Repository Settings That Enforce Good Behaviour

Teams should not rely entirely on developers remembering the rules.

GitHub branch protection or rulesets can enforce:

  • Pull requests before merging

  • One or more approving reviews

  • Approval from code owners

  • Passing automated checks

  • Resolution of review conversations

  • Up-to-date branches

  • Restricted direct pushes

  • Restricted force pushes

  • Dismissal of stale approvals after new changes

See GitHub’s documentation on protected branches.

A Practical Daily Workflow

For most team contributions, this workflow is sufficient:

# Update the base branch
git switch main
git fetch origin
git pull --ff-only origin main

# Create a new branch
git switch -c feature/user-profile

# Make and inspect changes
git status
git diff

# Stage and commit
git add path/to/file
git diff --staged
git commit -m "Add user profile management"

# Push the branch
git push -u origin feature/user-profile

Then:

  1. Open a pull request.

  2. Review your own changes.

  3. Request reviewers.

  4. Allow automated checks to run.

  5. Address review feedback.

  6. Obtain approval.

  7. Merge according to team policy.

  8. Delete the completed branch.

  9. Update your local main.

Final Principle

Git commands are only part of team collaboration.

The real discipline is understanding that shared code must move through a controlled process:

One focused task
One dedicated branch
Clear commits
One reviewable pull request
Independent review
Passing automated checks
Authorized merge
Clean branch history

The objective is not merely to get your code into main. The objective is to contribute changes that the team can understand, review, trust, maintain, and safely release.

For additional practice, use the interactive courses on GitHub Skills and consult the free Pro Git book.

Additional Resources for Further Study

The following resources provide more detailed explanations and practical exercises.

Official Documentation

  • Pro Git Book: A comprehensive free book covering Git basics, remotes, branches, merging, rebasing, distributed workflows, GitHub, and advanced Git tools.

  • GitHub Pull Requests Documentation: Official guidance on branches, commits, forks, pull requests, reviews, conflicts, status checks, and merging.

  • GitHub Protected Branches Documentation: Explains how teams can require reviews, status checks, and other conditions before code is merged.

  • Git Remote Documentation: The official reference for adding, viewing, renaming, and removing remote repositories.

  • Conventional Commits: A specification for writing consistent and structured commit messages.

Practical GitHub Exercises

  • GitHub Skills: Interactive exercises for learning Git, GitHub, pull requests, code reviews, merge conflicts, GitHub Actions, and other collaboration features.

  • Review Pull Requests Exercise: A practical GitHub exercise covering how to request reviews, provide feedback, suggest changes, and approve pull requests.

  • Resolve Merge Conflicts Exercise: A guided exercise explaining why conflicts occur and how to resolve them.

  • First Contributions Repository: A beginner-friendly repository where developers can practise forking, cloning, branching, committing, pushing, and opening a pull request.

Video Resources

The best way to understand this workflow is to practise it. Create a small repository with another developer, protect the main branch, create issues, work from separate branches, open pull requests, review one another’s changes, resolve a deliberate conflict, and merge only after approval.