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

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:
Working directory: The files you are currently editing.
Staging area: The changes selected for the next commit.
Local repository: Commits saved on your computer.
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.mdCONTRIBUTING.mdPull 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:
Understand the concern.
Ask for clarification when necessary.
Update the same branch.
Commit and push the correction.
Respond to the comment.
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:
- Identify the conflicted files:
git status
- Open each file and look for conflict markers:
<<<<<<< HEAD
Your version
=======
Incoming version
>>>>>>> origin/main
Decide what the final code should contain.
Remove the conflict markers.
Test the combined result.
Stage the resolved files:
git add path/to/file
- 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
.envfiles.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:
Open a pull request.
Review your own changes.
Request reviewers.
Allow automated checks to run.
Address review feedback.
Obtain approval.
Merge according to team policy.
Delete the completed branch.
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
GitHub for Beginners Video Series: GitHub’s beginner series covering repositories, Git commands, branches, pull requests, merging, and related workflows.
How to Create a Pull Request: A short practical demonstration of creating a pull request and proposing changes for review.
How to Merge a Pull Request: A beginner-friendly GitHub video covering pull request merging and conflict resolution.
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.


