Collaboration on GitHub
10 min read
Introduction
Working alone with Git and working in collaboration can be two entirely different things.
When working alone you work mostly sequentially. You have full control and context of every file and commit coming in and at what time. This makes it relatively easy to manage, navigate or fix an issue.
When working in collaboration however, multiple developers are editing the same files at the same time (parallel), meaning you dont have full context over every file and commit, and you need a way to manage the project to still be organized and stable, even while features are flying in.
Git and GitHub have become the go-to pieces of tech for collaboration among developers.
- Git gives you the tools (branches, commits, merges).
- GitHub gives you the platform (PRs, reviews, issues).
Together, they make sure no one overwrites each other’s work, everyone’s changes are visible and trackable, and that the project grows without turning into chaos.
In this writeup, we’ll break down the essentials of collaborating with Git so you can jump into any team project with confidence.
1. Cloning and Forking – git clone.
Before you can start contributing to a project on GitHub, you first need a copy of the code.
There are two main ways to do this: cloning and forking
Cloning Repos
The beginning of most collaborations has to do with cloning repos.
It is how you get a project on your machine for the first time.
It downloads the entire repository including all files, branches, and history, leaving you with a complete local copy.
To clone a remote repository
1. Open the repository on Copy GitHub and copy the repository url (shown below)
2. Then using the repo url run the following command on your bash cli:
git clone <repo-url>
Or alternatively you can click the clone repository link of your ide (If using any modern text editor or IDE)
Now you have a local copy of the project to work on.
Forking Repos
Forking a repository creates a personal copy of someone else’s repository on your GitHub account.
Forking is especially common when you want to contribute to an open-source project or experiment with changes without affecting the original repository.
To fork a remote repository
1. Click the Fork button (top-right of a repository page on GitHub). This creates your own copy of the repo under your account.
2. From there you can clone your fork onto your local machine
git clone <your-fork-url>
Note
While cloning simply downloads a copy of a repository to your local machine, forking creates a personal copy of someone else’s repository on your GitHub account, which you can then clone to make changes.
2. Remote Basics – origin, upstream, tracking branches.
Remote Repositories
A remote repository is a version of your project that is that is hosted on a server or network location, separate from your local working copy.
GitHub is a cloud-based platform that provides hosting services for (remote) repositories.
When you clone a repo, you’re not just copying files, you’re also linking your local project to where it lives online. That “link” is called a remote.
Remote Origin
A remote origin is the name of the main repo URL you’re working with (mostly the repo you cloned).
When you first clone a repository, Git automatically sets up a default remote called origin and by convention, this points to the main source repo (the one on GitHub) you cloned from.
So when you run git clone https://github.com/user/project.git, git downloads the repository and sets up a remote called origin, pointing to https://github.com/user/project.git.
Remote Upstream
A remote upstream is a remote repository that your current branch is currently in sync with.
Unlike origin which is the remote that points to your copy of the repo , upstream is usually the remote that points to the original source repo you forked from.
A typical fork setup (where you'd need an upstream) looks like this:
You fork a project on GitHub, and then you clone your fork.
But the original project that you forked from is still out there, and will keep getting new features.
To keep your fork in sync with it, you add a new remote called upstream, which points to the original repo.
git remote add upstream https://github.com/their-org/project.git
And if you want to fetch from that upstream to keep your branch up to date:
git fetch upstream
git merge upstream/main
Note
If you didn’t fork a repo (You cloned one), Git only sets up one remote by default - "origin" and there won’t be an upstream unless you add it yourself.
Tracking Branches
When you clone a repository, Git doesn’t just bring down the files, it also connects your local branches to their corresponding remote branches.
A tracking branch is simply a local branch that’s linked to a remote branch.
This link makes it easier for git to know which remote branch to fetch from or push to.
i.e:
When you initially clone a repo in your ide, git creates a local branch main. That local main automatically tracks origin/main (remote main).
This way running git pull or git push, you pulls or pushes changes from/to origin/main.
Without tracking, you’d have to type the full command every time. i.e:
git pull origin main
git push origin main
Tracking branches save you that repetition.
Note
"main" above represents the branch name for your main branch. Though it doesn’t always have the name main. It can also be named "master", "production" etc.
Creating a Tracking Branch Manually
There are reasons you may want to track a branch manually. e.g.
- You created a new local branch first before remote.
- You pulled a branch from the remote without tracking (
git fetch origin). - You want to change the remote branch your local branch tracks.
You can set that up with:
git branch --set-upstream-to=origin/feature-xyz
Now feature-xyz (local) tracks origin/feature-xyz (remote).
3. Syncing Work – git fetch, git pull, git push.
Now that we've touched on the basics of remote repositories, and how they link to a local repository, we also need to learn how to live sync (keep up-to-date) changes between the local and remote repo, because git won't automatically do this for us.
The three most common commands for this are fetch, pull, and push.
git fetch - git fetch
This downloads new data (commits, branches, tags) from the remote into your local repo, but it doesn’t change your working files.
git pull - git pull
This does a fetch + apply. It downloads the new changes and instantly applies them to your current branch.
git push - git push
This sends your commits from your local branch to the remote branch it’s tracking. It’s how you publish your changes so others can see them.
In Summary
Use fetch when you want to preview remote changes before applying them.
Use pull when you’re ready to bring remote changes into your local branch.
Use push when you’re done making changes locally and want to share them remotely.
4. Branching for Teams (Importance in teamwork).
When working solo, you might get away with committing everything to the main branch. But in team environments, that approach quickly becomes chaotic.
Effective use of branches solve this problem and makes collaborative development manageable and safe.
Why Branches Matter
Branches allow multiple people to work on different features simultaneously without constant disruption of each other's work.
The Main Branch Philosophy
Your main branch (often called main or master) should always be production ready. It's the source of truth that everyone builds from, hence it should always be in a working state.
If everyone commits directly to main, you'll constantly deal with:
- Merge conflicts as people edit the same files
- Broken code that blocks other developers
- Difficulty tracking which changes belong to which feature
- No easy way to review code before it goes live
This emphasizes the essence of branching when working with a team.
Feature Branches
There are many branching conventions but the most common branching strategy is to create a feature branch for each new feature or bug fix.
git checkout -b feature-user-authentication
With this you can make changes, commit them, and experiment freely. Your work is isolated from main and from other developers' branches.
Branch Naming Conventions
When working with teams branching naming conventions are often adopted to keep branches organized. They are agreed upon rules or patterns for naming your branches in a Git repository.
They provide consistency, clarity, and traceability so that:
-
Everyone on a team can immediately tell what a branch is for.
-
Your repository stays organized, especially with many contributors.
-
AI Automation tools (like CI/CD pipelines(for DevOps)) can detect branch types automatically.
There are many popular naming conventions for branches, with the most popular being the Git flow and Github flow conventions.👇🏽
| Purpose | Convention | Example |
|---|---|---|
| New feature | feature/<name> | feature/add-auth |
| Bug fixes | bugfix/<name> | bugfix/fix-login-error |
| Emergency fixes | hotfix/<name> | hotfix/urgent-prod-fix |
| Preparing for release | release/<version> | release/1.3.0 |
| Maintenance tasks | chore/<name> | chore/update-readme |
These prefixes make it immediately clear what type of work is happening in each branch.
Working with Team Branches
Once you've pushed your feature branch to the remote repository, your teammates can check it out and collaborate:
// Push your branch to the remote :
git push -u origin feature-user-authentication
// A teammate can then fetch and checkout to your branch :
git fetch origin
git checkout feature-user-authentication
Keeping Your Branch Updated
While you're working on your feature branch, other developers might be merging their changes into main. To avoid falling too far behind, regularly sync your branch with main by checking out to main, pulling from main, then checking out back into your branch:
git checkout main
git pull origin main
git checkout your-branch-name
Then you can merge main to your branch with:
git merge main
Branch Protection Rules
On GitHub, you'd often find that teams set up branch protection rules for main to enforce best practices:
- Require pull request reviews before merging
- Require status checks to pass (automated tests)
- Prevent direct pushes to main
- Require up-to-date branches before merging
These rules ensure that code quality stays high and nothing reaches production without proper review.
5. Pull Requests (PRs) (what they are, how to create one)
A Pull Request (PR) is one of the most essential parts of collaboration with git. It is the primary way teams review and merge code in Git-based workflows.
If you want to go collaborating with git, you need to be familiar with the concept of Pull Requests.
What is a Pull Request?
When working in a team, there are usually general contributors and project maintainers. Everybody contributes to the project (usually on their own branch), but project maintainers are responsible for the quality of code that is pulled into production.
Regular contributors need to be able request their changes to be reviewed by maintainers and pulled into the main branch (production). This is where the concept of Pull Requests come into play.
A Pull Request is a request to project maintainers to review and merge changes from one branch into another.
It is important as it provides:
- A space for code review and discussion.
- A record of what changed and why.
- A place to run automated tests before merging.
- A clear approval process before code goes live.
Without PRs merge conflicts and unprecedented errors from branches will be a recurring issue.
Creating a Pull Request on GitHub
Creating a pull request starts when your branch is pushed to github, and ends with a maintainer pulling your request after review.
1. Push Your Branch
First, make sure your feature branch is pushed to GitHub:
git push -u origin feature/your-feature-name
2. Open the Pull Request
Navigate to your repository on GitHub. You'll typically see a banner suggesting you create a PR for your recently pushed branch.
Click "Compare & pull request".
Alternatively, go to the "Pull requests" tab and click "New pull request".
3. Choose Your Branches
Select which branch you want to merge from (your feature branch) and which branch you want to merge into (usually main).
GitHub will show you all the changes (the "diff") between these branches.
4. Write a Clear Description
Give your PR a descriptive title and explain what your changes do:
A good PR description helps reviewers understand your work quickly.
5. Request For Reviewers
On the right sidebar, you can request specific team members to review your code. Many teams require at least one approval before merging.
6. Submit the Pull Request
Click "Create pull request". Your PR is now open for review!
Note
Pro tip: Keep your PR scope focused (i.e single bug or feature). Smaller, focused PRs are easier to review and more likely to be merged quickly than massive changes touching dozens of files.
Common PR Etiquette
- Keep PRs focused: One feature or fix per PR
- Write clear commit messages: Explain the "why" not just the "what"
- Respond promptly to feedback: Reviewers are taking time to help you
- Test your changes: Don't rely on reviewers to catch bugs
- Update documentation: If your code changes behavior, update the docs
6. Code Review Flow ( Review, Approval, and Merging of PRs).
After you create a request, it goes through several stages of screening before it is pulled into main by reviewers.
Team members will review your code, leaving comments on specific lines or sections:
You can respond to comments, make additional commits to address feedback, and push them to the same branch.
The Pull Request always updates automatically and the new changes(commits) appear in the PR immediately.
Approval and Merging
Once reviewers approve and all checks pass, the PR can be merged, by clicking the green "Merge Pull Request" button, and selecting the appropriate merge type.
After merging a PR, it's good practice to delete the feature branch—you can do this directly from GitHub or locally:
git branch -D feature-user-authentication
Merge Types
Merge Commit creates a new merge commit that combines the feature branch into main while keeping the full branch history.
Preserves entire context but history can get messy
Squash & Merge turns all commits from a PR into one clean commit before merging into main.
Allows for a simple history but loses detailed commit history
Rebase & Merge replays the feature branch commits on top of the latest main to create a perfectly linear history.
Very clean, chronological history can be risky because it rewrites commit history (Popular in more experienced dev teams)
Draft Pull Requests
If you want early feedback but your work isn't ready for review, create a draft PR. This signals to your team that it's work-in-progress.
You can convert it to a regular PR when you're ready for full review.
Pull Requests in Forked Repositories
When contributing to open-source projects, you typically:
- Fork the repository to your account
- Clone your fork locally
- Create a feature branch and make changes
- Push to your fork
- Open a pull request from your fork to the original repository
The process is the same, but the PR goes from your fork to the upstream repository.
Pull Requests are a conversation about code quality, a teaching tool, and a permanent record of how your project evolved.
7. Merge Conflicts in Teams.
If you’ve spent even a week around developers, you’ve probably heard them sigh about merge conflicts. It is one of the most common (and annoying) parts of collaboration. But you’re in safe hands as this chapter will show you exactly how to understand and resolve them without any drama.
Merge conflicts happen when multiple people edit the same lines of code differently and Git can't automatically decide which version to keep, so it asks you to resolve it manually.
For example when two people are working on their own branch both originated from the same branch and they both edit the same sentence in a file:
One person changes const subject = "english" to const subject = "math"
Another changes const subject = "english" to const subject = "science"
When it’s time to merge their work, the document isn’t sure which number is correct. That’s the situation Git runs into and it needs you to decide.
What a Merge Conflict Looks Like
When Git encounters a conflict, it marks the conflicting sections in your file:
function greetUser() {
<<<<<<< HEAD
const name = "Alice";
=======
const name = "Bob";
>>>>>>> feature-greeting-update
}
Understanding the markers:
<<<<<<< HEAD— Your current version=======— Separator>>>>>>> feature-greeting-update— Incoming version
Merge Conflicts Occur When:
- Two branches change the same line differently (Shown above)
- One branch deletes a file while another edits it
- Changes overlap or are too close together(Conflicting edits around the same block can confuse Git.)
- Renaming files or moving files in different branches
Resolving Conflicts
Step 1: Identify the Conflict
git merge feature-branch
# Output:
CONFLICT (content): Merge conflict in greet.js
Automatic merge failed; fix conflicts and then commit the result.
Step 2: Edit the File
Open the conflicted file and decide what to keep. Remove all conflict markers and save:
// Option 1: Keep yours
function greetUser() {
const name = "Alice";
}
// Option 2: Keep theirs
function greetUser() {
const name = "Bob";
}
// Option 3: Combine both
function greetUser() {
const name = "Alice"; // Kept the better name
}
Step 3: Mark as Resolved
git add greet.js
git commit -m "Resolve merge conflict in greetUser"
Avoiding Conflicts
- Pull frequently to stay synced with main
- Communicate when multiple people work on the same file
- Keep branches short-lived and merge often
- Make smaller commits for easier conflict resolution
Resolving Conflicts in Pull Requests (Important!)
When a PR has conflicts, resolve them locally (on your computer ide), by:
Checking out to main:
git checkout main
Pulling:
git pull origin main
Checking out back to the branch with the conflict:
git checkout feature-branch
Merging main into it:
git merge main
Resolving the conflicts, then commiting and pushing the PR back to the remote:
git add .
git commit -m "Resolve merge conflicts"
git push origin feature-branch
Finally to abort a merge and leave it for later:
git merge --abort
Note
Pro tip: Most modern editors (VS Code, IntelliJ) highlight conflicts and offer buttons to quickly accept changes. Don't panic—conflicts are normal in team environments!
8. Forking Workflow (Contribution to Open Source).
Forking is how you contribute to projects you don't have write access to. It creates your own copy of the repository on GitHub.
We've briefly touched on forking in an above section, now we want to touch on the typical oprn source contribution workflow, which usually begins with forking a repository.
The Contribution Process
1. Fork the Repository
Click the Fork button on GitHub. This creates: github.com/original-owner/project → github.com/your-username/project
2. Clone Your Fork
git clone https://github.com/your-username/project.git
cd project
3. Add Upstream Remote
Connect to the original project to sync updates:
git remote add upstream https://github.com/original-owner/project.git
Verify:
git remote -v
# origin → your fork
# upstream → original project
4. Create a Feature Branch
git checkout -b fix-typo-in-readme
5. Make Changes and Commit
git add .
git commit -m "Fix typo in installation instructions"
6. Push to Your Fork
git push origin fix-typo-in-readme
7. Create a Pull Request
Go to your fork on GitHub and click "Compare & pull request". The PR goes from your fork to the original repository.
8. Keep Your Fork Synced
git fetch upstream
git checkout main
git merge upstream/main
git push origin main
Best Practices
- Read CONTRIBUTING.md before submitting
- Start small (typos, docs, tests)
- Write clear PR descriptions explaining what and why
- Be patient with maintainers (they're often volunteers)
- Test your changes before submitting
Note
Look for issues labeled "good first issue" or "beginner-friendly" for your first contribution.
9. Basic GitHub Features (Issues, Discussions, Projects).
GitHub provides collaboration tools beyond just hosting code.
GitHub Issues
Issues are tickets for bugs, features, or tasks.
Creating a Good Issue
Title: Add dark mode support
Description: Users have requested dark mode for better readability.
Proposed Solution:
- Add theme toggle in settings
- Store preference in localStorage
- Apply dark theme CSS
Acceptance Criteria:
- [ ] Theme toggle works
- [ ] Preference persists
- [ ] All pages support dark mode
Linking Issues
git commit -m "Add dark mode. Fixes #42"
Using Fixes #42 or Closes #42 automatically closes the issue when merged.
GitHub Discussions
For open-ended conversations that aren't specific tasks:
- Q&A with maintainers
- Feature brainstorming
- Community chat
| Use Issues For | Use Discussions For |
|---|---|
| "Login button is broken" | "What's the best authentication approach?" |
| "Add CSV export" | "Should we support CSV or JSON?" |
| Other Actionable tasks | Other Open-ended questions |
GitHub Projects
Kanban-style boards for managing work. Choose from:
- Board view: To Do, In Progress, Done columns
- Table view: Spreadsheet layout
- Roadmap view: Timeline for releases
Drag issues between columns as work progresses.
Labels & Milestones
Labels categorize issues:
bug(red) — Something's brokenenhancement(blue) — New featuregood first issue(green) — Beginner-friendly
Milestones group issues into releases:
- v1.0 Release
- Q1 2025 Goals
Note
Start simple. Issues and PRs might be enough. You can then add projects and discussions as your team grows and you see the need.
10. Team Workflows (Intro to GitHub Flow).
GitHub Flow is a simple, branch-based workflow where main is always deployable.
The Process
1. Create a Branch
git checkout main
git pull origin main
git checkout -b feature-add-search
2. Make Commits
git commit -m "Add search input component"
git commit -m "Connect search to backend API"
3. Open a Pull Request
git push origin feature-add-search
Open the PR on GitHub—even if work is still in progress (use draft PRs).
4. Discuss and Review
Team members review code and suggest changes. Make updates and push—the PR updates automatically.
5. Deploy and Test
Deploy to staging, test thoroughly, fix any issues.
6. Merge to Main
Once approved and tests pass, merge the PR. This often triggers automatic deployment to production.
7. Delete the Branch
git branch -d feature-add-search
git push origin --delete feature-add-search
Core Principles
- Main is always deployable — Never commit broken code
- Branches are short-lived — Merge within 1-3 days
- Deploy frequently — Small changes are safer
- Always use PRs — Even for small changes
- Automate testing — Run tests on every PR
Example Timeline
Monday 9am: Create branch
Monday 3pm: Open PR
Tuesday 2pm: Get approval
Tuesday 4pm: Merge & auto-deploy
Tuesday 5pm: Delete branch
Total time: ~1.5 days
Branch Protection
Set up rules on GitHub:
- Require PR reviews
- Require passing tests
- Prevent force pushes
- Require up-to-date branches
When to Use Alternatives
GitHub Flow assumes continuous deployment. If you need:
- Scheduled releases
- Multiple supported versions
- Long QA cycles
Consider Git Flow or GitLab Flow instead.
Note
Remember: Workflows are tools, not rules. Adapt GitHub Flow to fit your team. The goal is smooth collaboration and safe deployments.
11. Conclusion and Final Notes
Well done!! You have now learnt how to use Git and Github to collaborate effectively. You should now be comfortable working with a team on projects in an organization, and even contributing open source projects.
Remember the only way to get really good at this to practice it, so start contributing. One line at a time.
Subscribe to our newsletter below to be notified when future articles get released.
Thank you for reading!!
You might also like:

Git and Github: A Beginner's Guide
A comprehensive guide to understanding Git and GitHub for beginners. Learn version control, collaboration, and essential commands to manage your code effectively.